Skip to content

Commit ba40140

Browse files
authored
support encrypted s3 bucket for plan uploads (#1882)
1 parent aa90fe3 commit ba40140

File tree

3 files changed

+78
-14
lines changed

3 files changed

+78
-14
lines changed

action.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,18 @@ inputs:
100100
upload-plan-destination-s3-bucket:
101101
description: Name of the destination bucket for AWS S3. Should be provided if destination == aws
102102
required: false
103+
upload-plan-destination-s3-encryption-enabled:
104+
description: If encryption is to be enabled for s3 bucket
105+
required: false
106+
default: "false"
107+
upload-plan-destination-s3-encryption-type:
108+
description: the type of encryption to use for the S3 bucket, either AES256 or KMS
109+
required: false
110+
default: "AES256"
111+
upload-plan-destination-s3-encryption-kms-key-id:
112+
description: for encryption of type KMS you need to specify the KMS key ID to use
113+
required: false
114+
103115
upload-plan-destination-gcp-bucket:
104116
description: Name of the destination bucket for a GCP bucket. Should be provided if destination == gcp
105117
required: false
@@ -367,6 +379,9 @@ runs:
367379
shell: bash
368380
env:
369381
PLAN_UPLOAD_DESTINATION: ${{ inputs.upload-plan-destination }}
382+
PLAN_UPLOAD_S3_ENCRYPTION_ENABLED: ${{ inputs.upload-plan-destination-s3-encryption-enabled }}
383+
PLAN_UPLOAD_S3_ENCRYPTION_TYPE: ${{ inputs.upload-plan-destination-s3-encryption-type }}
384+
PLAN_UPLOAD_S3_ENCRYPTION_KMS_ID: ${{ inputs.upload-plan-destination-s3-encryption-kms-key-id }}
370385
GOOGLE_STORAGE_LOCK_BUCKET: ${{ inputs.google-lock-bucket }}
371386
GOOGLE_STORAGE_PLAN_ARTEFACT_BUCKET: ${{ inputs.upload-plan-destination-gcp-bucket }}
372387
AWS_S3_BUCKET: ${{ inputs.upload-plan-destination-s3-bucket }}
@@ -404,6 +419,9 @@ runs:
404419
env:
405420
actionref: ${{ github.action_ref }}
406421
PLAN_UPLOAD_DESTINATION: ${{ inputs.upload-plan-destination }}
422+
PLAN_UPLOAD_S3_ENCRYPTION_ENABLED: ${{ inputs.upload-plan-destination-s3-encryption-enabled }}
423+
PLAN_UPLOAD_S3_ENCRYPTION_TYPE: ${{ inputs.upload-plan-destination-s3-encryption-type }}
424+
PLAN_UPLOAD_S3_ENCRYPTION_KMS_ID: ${{ inputs.upload-plan-destination-s3-encryption-kms-key-id }}
407425
GOOGLE_STORAGE_LOCK_BUCKET: ${{ inputs.google-lock-bucket }}
408426
GOOGLE_STORAGE_PLAN_ARTEFACT_BUCKET: ${{ inputs.upload-plan-destination-gcp-bucket }}
409427
AWS_S3_BUCKET: ${{ inputs.upload-plan-destination-s3-bucket }}

libs/storage/aws_plan_storage.go

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,53 @@ type S3Client interface {
2424
DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error)
2525
}
2626

27+
type AwsS3EncryptionType string
28+
29+
const (
30+
ServerSideEncryptionAes256 AwsS3EncryptionType = "AES256"
31+
ServerSideEncryptionAwsKms AwsS3EncryptionType = "aws:kms"
32+
)
33+
2734
type PlanStorageAWS struct {
28-
Client S3Client
29-
Bucket string
30-
Context context.Context
35+
Client S3Client
36+
Bucket string
37+
Context context.Context
38+
EncryptionEnabled bool
39+
EncryptionType AwsS3EncryptionType
40+
KMSEncryptionId string
3141
}
3242

43+
func NewAWSPlanStorage(bucketName string, encryptionEnabled bool, encryptionType string, KMSEncryptionId string) (*PlanStorageAWS, error) {
44+
if bucketName == "" {
45+
return nil, fmt.Errorf("AWS_S3_BUCKET is not defined")
46+
}
47+
ctx, client, err := GetAWSStorageClient()
48+
if err != nil {
49+
return nil, fmt.Errorf("could not retrieve aws storage client")
50+
}
51+
planStorage := &PlanStorageAWS{
52+
Context: ctx,
53+
Client: client,
54+
Bucket: bucketName,
55+
}
56+
if encryptionEnabled {
57+
planStorage.EncryptionEnabled = true
58+
if encryptionType == "AES256" {
59+
planStorage.EncryptionType = ServerSideEncryptionAes256
60+
} else if encryptionType == "KMS" {
61+
if KMSEncryptionId == "" {
62+
return nil, fmt.Errorf("KMS encryption requested but no KMS key specified")
63+
}
64+
planStorage.EncryptionType = ServerSideEncryptionAwsKms
65+
planStorage.KMSEncryptionId = KMSEncryptionId
66+
} else {
67+
return nil, fmt.Errorf("unknown encryption type specified for aws plan bucket: %v", encryptionType)
68+
}
69+
}
70+
71+
return planStorage, nil
72+
73+
}
3374
func (psa *PlanStorageAWS) PlanExists(artifactName, storedPlanFilePath string) (bool, error) {
3475
input := &s3.HeadObjectInput{
3576
Bucket: aws.String(psa.Bucket),
@@ -59,6 +100,15 @@ func (psa *PlanStorageAWS) StorePlanFile(fileContents []byte, artifactName, file
59100
Bucket: aws.String(psa.Bucket),
60101
Key: aws.String(fileName),
61102
}
103+
104+
// support for encryption
105+
if psa.EncryptionEnabled {
106+
input.ServerSideEncryption = types.ServerSideEncryption(psa.EncryptionType)
107+
if psa.EncryptionType == ServerSideEncryptionAwsKms {
108+
input.SSEKMSKeyId = aws.String(psa.KMSEncryptionId)
109+
}
110+
}
111+
62112
_, err := psa.Client.PutObject(psa.Context, input)
63113
if err != nil {
64114
log.Printf("Failed to write file to bucket: %v", err)

libs/storage/plan_storage.go

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -235,18 +235,14 @@ func NewPlanStorage(ghToken string, ghRepoOwner string, ghRepositoryName string,
235235
Context: ctx,
236236
}
237237
case uploadDestination == "aws":
238-
ctx, client, err := GetAWSStorageClient()
239-
if err != nil {
240-
return nil, fmt.Errorf(fmt.Sprintf("Failed to create AWS storage client: %s", err))
241-
}
242238
bucketName := strings.ToLower(os.Getenv("AWS_S3_BUCKET"))
243-
if bucketName == "" {
244-
return nil, fmt.Errorf("AWS_S3_BUCKET is not defined")
245-
}
246-
planStorage = &PlanStorageAWS{
247-
Context: ctx,
248-
Client: client,
249-
Bucket: bucketName,
239+
encryptionEnabled := os.Getenv("PLAN_UPLOAD_S3_ENCRYPTION_ENABLED") == "true"
240+
encryptionType := os.Getenv("PLAN_UPLOAD_S3_ENCRYPTION_TYPE")
241+
encryptionKmsId := os.Getenv("PLAN_UPLOAD_S3_ENCRYPTION_KMS_ID")
242+
var err error
243+
planStorage, err = NewAWSPlanStorage(bucketName, encryptionEnabled, encryptionType, encryptionKmsId)
244+
if err != nil {
245+
return nil, fmt.Errorf("error while creating AWS plan storage: %v", err)
250246
}
251247
case uploadDestination == "gitlab":
252248
//TODO implement me

0 commit comments

Comments
 (0)