Skip to content

Commit 0aef528

Browse files
committed
WIP
1 parent 9e91b97 commit 0aef528

File tree

4 files changed

+102
-11
lines changed

4 files changed

+102
-11
lines changed

example/main.go

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func main() {
3131
dynamoDBClient := dynamodb.NewFromConfig(cfg)
3232

3333
// Initialize the key material store
34-
materialStore, err := store.NewKeyMaterialStore(dynamoDBClient, dynamoDBTableName)
34+
materialStore, err := store.NewMetaStore(dynamoDBClient, dynamoDBTableName)
3535
if err != nil {
3636
log.Fatalf("Failed to create key material store: %v", err)
3737
}
@@ -175,6 +175,24 @@ func main() {
175175
}
176176
fmt.Println("Encrypted item deleted successfully.")
177177

178+
// Paginate and decrypt items
179+
paginator, err := ec.GetPaginator("Scan")
180+
if err != nil {
181+
log.Fatalf("Failed to get paginator: %v", err)
182+
}
183+
184+
scanInput = &dynamodb.ScanInput{
185+
TableName: aws.String(tableName),
186+
}
187+
188+
err = paginator.Scan(ctx, scanInput, func(page *dynamodb.ScanOutput, lastPage bool) bool {
189+
fmt.Printf("Decrypted page results: %v\n", page.Items)
190+
return !lastPage // return false to stop paginating
191+
})
192+
if err != nil {
193+
log.Fatalf("Failed during paginated scan: %v", err)
194+
}
195+
178196
}
179197

180198
func createTableIfNotExists(ctx context.Context, client *dynamodb.Client, tableName string) error {

pkg/encrypted/client.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,72 @@ type PrimaryKeyInfo struct {
3030
SortKey string
3131
}
3232

33+
// EncryptedPaginator is a paginator for encrypted DynamoDB items.
34+
type EncryptedPaginator struct {
35+
client *EncryptedClient
36+
nextToken map[string]types.AttributeValue
37+
}
38+
39+
// NewEncryptedPaginator creates a new instance of EncryptedPaginator.
40+
func NewEncryptedPaginator(client *EncryptedClient) *EncryptedPaginator {
41+
return &EncryptedPaginator{
42+
client: client,
43+
nextToken: nil,
44+
}
45+
}
46+
47+
func (p *EncryptedPaginator) Query(ctx context.Context, input *dynamodb.QueryInput, fn func(*dynamodb.QueryOutput, bool) bool) error {
48+
for {
49+
if p.nextToken != nil {
50+
input.ExclusiveStartKey = p.nextToken
51+
}
52+
53+
output, err := p.client.Query(ctx, input)
54+
if err != nil {
55+
return err
56+
}
57+
58+
lastPage := len(output.LastEvaluatedKey) == 0
59+
if !fn(output, lastPage) {
60+
break
61+
}
62+
63+
if lastPage {
64+
break
65+
}
66+
67+
p.nextToken = output.LastEvaluatedKey
68+
}
69+
70+
return nil
71+
}
72+
73+
func (p *EncryptedPaginator) Scan(ctx context.Context, input *dynamodb.ScanInput, fn func(*dynamodb.ScanOutput, bool) bool) error {
74+
for {
75+
if p.nextToken != nil {
76+
input.ExclusiveStartKey = p.nextToken
77+
}
78+
79+
output, err := p.client.Scan(ctx, input)
80+
if err != nil {
81+
return err
82+
}
83+
84+
lastPage := len(output.LastEvaluatedKey) == 0
85+
if !fn(output, lastPage) {
86+
break
87+
}
88+
89+
if lastPage {
90+
break
91+
}
92+
93+
p.nextToken = output.LastEvaluatedKey
94+
}
95+
96+
return nil
97+
}
98+
3399
// EncryptedClient facilitates encrypted operations on DynamoDB items.
34100
type EncryptedClient struct {
35101
client DynamoDBClientInterface
@@ -51,6 +117,13 @@ func NewEncryptedClient(client DynamoDBClientInterface, materialsProvider provid
51117
}
52118
}
53119

120+
func (ec *EncryptedClient) GetPaginator(operationName string) (*EncryptedPaginator, error) {
121+
if operationName != "Query" && operationName != "Scan" {
122+
return nil, fmt.Errorf("unsupported operation for pagination: %s", operationName)
123+
}
124+
return NewEncryptedPaginator(ec), nil
125+
}
126+
54127
// PutItem encrypts an item and puts it into a DynamoDB table.
55128
func (ec *EncryptedClient) PutItem(ctx context.Context, input *dynamodb.PutItemInput) (*dynamodb.PutItemOutput, error) {
56129
// Encrypt the item, excluding primary keys

pkg/provider/kms.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ type AwsKmsCryptographicMaterialsProvider struct {
1515
KeyID string
1616
EncryptionContext map[string]string
1717
DelegatedKey *delegatedkeys.TinkDelegatedKey
18-
MaterialStore *store.KeyMaterialStore
18+
MaterialStore *store.MetaStore
1919
}
2020

2121
// NewAwsKmsCryptographicMaterialsProvider initializes a provider with the specified AWS KMS key ID, encryption context, and material store.
22-
func NewAwsKmsCryptographicMaterialsProvider(keyID string, encryptionContext map[string]string, materialStore *store.KeyMaterialStore) (CryptographicMaterialsProvider, error) {
22+
func NewAwsKmsCryptographicMaterialsProvider(keyID string, encryptionContext map[string]string, materialStore *store.MetaStore) (CryptographicMaterialsProvider, error) {
2323

2424
return &AwsKmsCryptographicMaterialsProvider{
2525
KeyID: keyID,

pkg/provider/store/store.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,21 @@ import (
1212
"github.com/cloudopsy/dynamodb-encryption-go/pkg/materials"
1313
)
1414

15-
type KeyMaterialStore struct {
15+
type MetaStore struct {
1616
DynamoDBClient *dynamodb.Client
1717
TableName string
1818
}
1919

20-
// NewKeyMaterialStore creates a new instance of KeyMaterialStore.
21-
func NewKeyMaterialStore(dynamoDBClient *dynamodb.Client, tableName string) (*KeyMaterialStore, error) {
22-
return &KeyMaterialStore{
20+
// NewMetaStore creates a new instance of MetaStore.
21+
func NewMetaStore(dynamoDBClient *dynamodb.Client, tableName string) (*MetaStore, error) {
22+
return &MetaStore{
2323
DynamoDBClient: dynamoDBClient,
2424
TableName: tableName,
2525
}, nil
2626
}
2727

2828
// StoreNewMaterial stores a new material along with its encryption context serialized as JSON.
29-
func (s *KeyMaterialStore) StoreNewMaterial(ctx context.Context, materialName string, material materials.CryptographicMaterials) error {
29+
func (s *MetaStore) StoreNewMaterial(ctx context.Context, materialName string, material materials.CryptographicMaterials) error {
3030
// Serialize the material description to a JSON string.
3131
materialDescriptionJSON, err := json.Marshal(material.MaterialDescription())
3232
if err != nil {
@@ -83,7 +83,7 @@ func (s *KeyMaterialStore) StoreNewMaterial(ctx context.Context, materialName st
8383
}
8484

8585
// RetrieveMaterial retrieves a material and its encryption context by materialName and version.
86-
func (s *KeyMaterialStore) RetrieveMaterial(ctx context.Context, materialName string, version int64) (map[string]string, string, error) {
86+
func (s *MetaStore) RetrieveMaterial(ctx context.Context, materialName string, version int64) (map[string]string, string, error) {
8787
// If version is less than 1, retrieve the latest version
8888
if version < 1 {
8989
var err error
@@ -135,7 +135,7 @@ func (s *KeyMaterialStore) RetrieveMaterial(ctx context.Context, materialName st
135135
return materialDescMap, wrappedKeysetBase64, nil
136136
}
137137

138-
func (s *KeyMaterialStore) getLastVersion(ctx context.Context, materialName string) (int64, error) {
138+
func (s *MetaStore) getLastVersion(ctx context.Context, materialName string) (int64, error) {
139139
input := &dynamodb.QueryInput{
140140
TableName: aws.String(s.TableName),
141141
KeyConditionExpression: aws.String("MaterialName = :materialName"),
@@ -172,7 +172,7 @@ func (s *KeyMaterialStore) getLastVersion(ctx context.Context, materialName stri
172172
}
173173

174174
// CreateTableIfNotExists checks if a DynamoDB table exists, and if not, creates it.
175-
func (s *KeyMaterialStore) CreateTableIfNotExists(ctx context.Context) error {
175+
func (s *MetaStore) CreateTableIfNotExists(ctx context.Context) error {
176176
_, err := s.DynamoDBClient.DescribeTable(ctx, &dynamodb.DescribeTableInput{
177177
TableName: aws.String(s.TableName),
178178
})

0 commit comments

Comments
 (0)