-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge commit 'aa0a60a122fd8cd13aefb664ac4282fee7518e40' into jt-psgo-…
…911-stream-token-encryption
- Loading branch information
Showing
12 changed files
with
260 additions
and
20 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
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,98 @@ | ||
package encryption | ||
|
||
import ( | ||
"context" | ||
"hash/crc32" | ||
|
||
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 | ||
} | ||
|
||
table := crc32.MakeTable(crc32.IEEE) | ||
|
||
encryptor.logger.Infof(ctx, "encryption key: %08x, %s", crc32.Checksum([]byte(encryptor.keyID), table), encryptor.keyID) | ||
encryptor.logger.Infof(ctx, "encryption metadata: %08x, %s", crc32.Checksum(additionalData, table), string(additionalData)) | ||
encryptor.logger.Infof(ctx, "encryption plaintext: %08x, %s", crc32.Checksum(plaintext, table), 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: %08x, %s", crc32.Checksum(response.GetCiphertext(), table), 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 | ||
} | ||
|
||
table := crc32.MakeTable(crc32.IEEE) | ||
|
||
encryptor.logger.Infof(ctx, "decryption key: %08x, %s", crc32.Checksum([]byte(encryptor.keyID), table), encryptor.keyID) | ||
encryptor.logger.Infof(ctx, "decryption metadata: %08x, %s", crc32.Checksum(additionalData, table), string(additionalData)) | ||
encryptor.logger.Infof(ctx, "decryption ciphertext: %08x, %s", crc32.Checksum(ciphertext, table), 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: %08x, %s", crc32.Checksum(response.GetPlaintext(), table), 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 | ||
} |
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,77 @@ | ||
package encryption | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/keboola/go-cloud-encrypt/pkg/cloudencrypt" | ||
|
||
"github.com/keboola/keboola-as-code/internal/pkg/log" | ||
"github.com/keboola/keboola-as-code/internal/pkg/utils/errors" | ||
) | ||
|
||
// LoggedEncryptor wraps another Encryptor and adds logging. | ||
type LoggedEncryptor struct { | ||
encryptor cloudencrypt.Encryptor | ||
logger log.Logger | ||
} | ||
|
||
func NewLoggedEncryptor(ctx context.Context, encryptor cloudencrypt.Encryptor, logger log.Logger) (*LoggedEncryptor, error) { | ||
return &LoggedEncryptor{ | ||
encryptor: encryptor, | ||
logger: logger, | ||
}, nil | ||
} | ||
|
||
func (encryptor *LoggedEncryptor) Encrypt(ctx context.Context, plaintext []byte, metadata cloudencrypt.Metadata) ([]byte, error) { | ||
meta := "" | ||
for k, v := range metadata { | ||
meta += k + ": " + v + ", " | ||
} | ||
|
||
encryptor.logger.Infof(ctx, "encryption metadata: "+meta) | ||
|
||
if len(plaintext) == 0 { | ||
err := errors.New("text should not be empty") | ||
encryptor.logger.Infof(ctx, "encryption error: %s", err.Error()) | ||
return nil, err | ||
} | ||
|
||
encryptedValue, err := encryptor.encryptor.Encrypt(ctx, plaintext, metadata) | ||
if err != nil { | ||
encryptor.logger.Infof(ctx, "encryption error: %s", err.Error()) | ||
return nil, err | ||
} | ||
|
||
encryptor.logger.Info(ctx, "encryption success") | ||
|
||
return encryptedValue, nil | ||
} | ||
|
||
func (encryptor *LoggedEncryptor) Decrypt(ctx context.Context, ciphertext []byte, metadata cloudencrypt.Metadata) ([]byte, error) { | ||
meta := "" | ||
for k, v := range metadata { | ||
meta += k + ": " + v + ", " | ||
} | ||
|
||
encryptor.logger.Infof(ctx, "decryption metadata: "+meta) | ||
|
||
if len(ciphertext) == 0 { | ||
err := errors.New("text should not be empty") | ||
encryptor.logger.Infof(ctx, "decryption error: %s", err.Error()) | ||
return nil, err | ||
} | ||
|
||
plaintext, err := encryptor.encryptor.Decrypt(ctx, ciphertext, metadata) | ||
if err != nil { | ||
encryptor.logger.Infof(ctx, "decryption error: %s", err.Error()) | ||
return nil, err | ||
} | ||
|
||
encryptor.logger.Info(ctx, "decryption success") | ||
|
||
return plaintext, nil | ||
} | ||
|
||
func (encryptor *LoggedEncryptor) Close() error { | ||
return encryptor.encryptor.Close() | ||
} |
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
Oops, something went wrong.