constellation/kms/storage/gcloudstorage.go

84 lines
2.1 KiB
Go
Raw Normal View History

package storage
import (
"context"
"errors"
"io"
"cloud.google.com/go/storage"
"google.golang.org/api/option"
)
// GoogleCloudStorage is an implementation of the Storage interface, storing keys in Google Cloud Storage buckets.
type GoogleCloudStorage struct {
projectID string
bucketName string
opts []option.ClientOption
}
// NewGoogleCloudStorage creates a Storage client for Google Cloud Storage: https://cloud.google.com/storage/docs/
//
// The parameter bucketOptions is optional, if not present default options will be created.
func NewGoogleCloudStorage(ctx context.Context, projectID, bucketName string, bucketOptions *storage.BucketAttrs, opts ...option.ClientOption) (*GoogleCloudStorage, error) {
gcStorage := &GoogleCloudStorage{
projectID: projectID,
bucketName: bucketName,
opts: opts,
}
// Make sure the storage bucket exists, if not create it
client, err := storage.NewClient(ctx, gcStorage.opts...)
if err != nil {
return nil, err
}
defer client.Close()
_, err = client.Bucket(gcStorage.bucketName).Attrs(ctx)
if err == nil {
return gcStorage, nil
}
if errors.Is(err, storage.ErrBucketNotExist) {
err = client.Bucket(gcStorage.bucketName).Create(ctx, gcStorage.projectID, bucketOptions)
}
return gcStorage, err
}
// Get returns a DEK from Google Cloud Storage by key ID.
func (s *GoogleCloudStorage) Get(ctx context.Context, keyID string) ([]byte, error) {
client, err := storage.NewClient(ctx, s.opts...)
if err != nil {
return nil, err
}
defer client.Close()
reader, err := client.Bucket(s.bucketName).Object(keyID).NewReader(ctx)
if err != nil {
if errors.Is(err, storage.ErrObjectNotExist) {
return nil, ErrDEKUnset
}
return nil, err
}
defer reader.Close()
return io.ReadAll(reader)
}
// Put saves a DEK to Google Cloud Storage by key ID.
func (s *GoogleCloudStorage) Put(ctx context.Context, keyID string, data []byte) error {
client, err := storage.NewClient(ctx, s.opts...)
if err != nil {
return err
}
defer client.Close()
writer := client.Bucket(s.bucketName).Object(keyID).NewWriter(ctx)
if _, err := writer.Write(data); err != nil {
return err
}
return writer.Close()
}