-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d347dd6
commit 64529cb
Showing
4 changed files
with
155 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
package encryption | ||
|
||
import ( | ||
"bytes" | ||
"compress/gzip" | ||
"encoding/base64" | ||
"encoding/gob" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
func Encode(data any) ([]byte, error) { | ||
var buffer bytes.Buffer | ||
|
||
// Base64 encode | ||
encoder := base64.NewEncoder(base64.StdEncoding, &buffer) | ||
|
||
// Gzip compress | ||
writer := gzip.NewWriter(encoder) | ||
|
||
// gob encode | ||
err := gob.NewEncoder(writer).Encode(data) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "gob encoder failed: %s", err.Error()) | ||
} | ||
|
||
err = writer.Close() | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "can't close gzip writer: %s", err.Error()) | ||
} | ||
|
||
err = encoder.Close() | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "base64 encoder failed: %s", err.Error()) | ||
} | ||
|
||
return buffer.Bytes(), nil | ||
} | ||
|
||
func Decode[T any](data []byte) (decoded T, err error) { | ||
// Base64 decode | ||
decoder := base64.NewDecoder(base64.StdEncoding, bytes.NewReader(data)) | ||
|
||
// Gzip uncompress | ||
reader, err := gzip.NewReader(decoder) | ||
if err != nil { | ||
return decoded, errors.Wrapf(err, "can't create gzip reader: %s", err.Error()) | ||
} | ||
|
||
defer reader.Close() | ||
|
||
// gob decode | ||
err = gob.NewDecoder(reader).Decode(&decoded) | ||
if err != nil { | ||
return decoded, errors.Wrapf(err, "gob decoder failed: %s", err.Error()) | ||
} | ||
|
||
return decoded, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package encryption | ||
|
||
import ( | ||
"context" | ||
|
||
kms "cloud.google.com/go/kms/apiv1" | ||
"cloud.google.com/go/kms/apiv1/kmspb" | ||
"github.com/keboola/go-cloud-encrypt/pkg/cloudencrypt" | ||
"github.com/pkg/errors" | ||
|
||
"github.com/keboola/keboola-as-code/internal/pkg/log" | ||
) | ||
|
||
// GCPEncryptor Implements Encryptor using Google Cloud's Key Management Service. | ||
type GCPEncryptor struct { | ||
client *kms.KeyManagementClient | ||
keyID string | ||
logger log.Logger | ||
} | ||
|
||
func NewGCPEncryptor(ctx context.Context, keyID string, logger log.Logger) (*GCPEncryptor, error) { | ||
client, err := kms.NewKeyManagementClient(ctx) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "can't create gpc kms client: %s", err.Error()) | ||
} | ||
|
||
return &GCPEncryptor{ | ||
client: client, | ||
keyID: keyID, | ||
logger: logger, | ||
}, nil | ||
} | ||
|
||
func (encryptor *GCPEncryptor) Encrypt(ctx context.Context, plaintext []byte, metadata cloudencrypt.Metadata) ([]byte, error) { | ||
additionalData, err := Encode(metadata) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
encryptor.logger.Infof(ctx, "encryption key: %s", encryptor.keyID) | ||
encryptor.logger.Infof(ctx, "encryption metadata: %s", string(additionalData)) | ||
encryptor.logger.Infof(ctx, "encryption plaintext: %s", string(plaintext)) | ||
|
||
request := &kmspb.EncryptRequest{ | ||
Name: encryptor.keyID, | ||
Plaintext: plaintext, | ||
AdditionalAuthenticatedData: additionalData, | ||
} | ||
|
||
response, err := encryptor.client.Encrypt(ctx, request) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "gcp encryption failed: %s", err.Error()) | ||
} | ||
|
||
encryptor.logger.Infof(ctx, "encryption ciphertext: %s", string(response.GetCiphertext())) | ||
|
||
return response.GetCiphertext(), nil | ||
} | ||
|
||
func (encryptor *GCPEncryptor) Decrypt(ctx context.Context, ciphertext []byte, metadata cloudencrypt.Metadata) ([]byte, error) { | ||
additionalData, err := Encode(metadata) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
encryptor.logger.Infof(ctx, "decryption key: %s", encryptor.keyID) | ||
encryptor.logger.Infof(ctx, "decryption metadata: %s", string(additionalData)) | ||
encryptor.logger.Infof(ctx, "decryption ciphertext: %s", string(ciphertext)) | ||
|
||
request := &kmspb.DecryptRequest{ | ||
Name: encryptor.keyID, | ||
Ciphertext: ciphertext, | ||
AdditionalAuthenticatedData: additionalData, | ||
} | ||
|
||
response, err := encryptor.client.Decrypt(ctx, request) | ||
if err != nil { | ||
return nil, errors.Wrapf(err, "gcp decryption failed: %s", err.Error()) | ||
} | ||
|
||
encryptor.logger.Infof(ctx, "decryption plaintext: %s", string(response.GetPlaintext())) | ||
|
||
return response.GetPlaintext(), nil | ||
} | ||
|
||
func (encryptor *GCPEncryptor) Close() error { | ||
err := encryptor.client.Close() | ||
if err != nil { | ||
return errors.Wrapf(err, "can't close gcp client: %s", err.Error()) | ||
} | ||
|
||
return nil | ||
} |