Skip to content

Commit

Permalink
support encrypted s3 bucket for plan uploads (#1882)
Browse files Browse the repository at this point in the history
  • Loading branch information
motatoes authored Feb 11, 2025
1 parent aa90fe3 commit ba40140
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 14 deletions.
18 changes: 18 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,18 @@ inputs:
upload-plan-destination-s3-bucket:
description: Name of the destination bucket for AWS S3. Should be provided if destination == aws
required: false
upload-plan-destination-s3-encryption-enabled:
description: If encryption is to be enabled for s3 bucket
required: false
default: "false"
upload-plan-destination-s3-encryption-type:
description: the type of encryption to use for the S3 bucket, either AES256 or KMS
required: false
default: "AES256"
upload-plan-destination-s3-encryption-kms-key-id:
description: for encryption of type KMS you need to specify the KMS key ID to use
required: false

upload-plan-destination-gcp-bucket:
description: Name of the destination bucket for a GCP bucket. Should be provided if destination == gcp
required: false
Expand Down Expand Up @@ -367,6 +379,9 @@ runs:
shell: bash
env:
PLAN_UPLOAD_DESTINATION: ${{ inputs.upload-plan-destination }}
PLAN_UPLOAD_S3_ENCRYPTION_ENABLED: ${{ inputs.upload-plan-destination-s3-encryption-enabled }}
PLAN_UPLOAD_S3_ENCRYPTION_TYPE: ${{ inputs.upload-plan-destination-s3-encryption-type }}
PLAN_UPLOAD_S3_ENCRYPTION_KMS_ID: ${{ inputs.upload-plan-destination-s3-encryption-kms-key-id }}
GOOGLE_STORAGE_LOCK_BUCKET: ${{ inputs.google-lock-bucket }}
GOOGLE_STORAGE_PLAN_ARTEFACT_BUCKET: ${{ inputs.upload-plan-destination-gcp-bucket }}
AWS_S3_BUCKET: ${{ inputs.upload-plan-destination-s3-bucket }}
Expand Down Expand Up @@ -404,6 +419,9 @@ runs:
env:
actionref: ${{ github.action_ref }}
PLAN_UPLOAD_DESTINATION: ${{ inputs.upload-plan-destination }}
PLAN_UPLOAD_S3_ENCRYPTION_ENABLED: ${{ inputs.upload-plan-destination-s3-encryption-enabled }}
PLAN_UPLOAD_S3_ENCRYPTION_TYPE: ${{ inputs.upload-plan-destination-s3-encryption-type }}
PLAN_UPLOAD_S3_ENCRYPTION_KMS_ID: ${{ inputs.upload-plan-destination-s3-encryption-kms-key-id }}
GOOGLE_STORAGE_LOCK_BUCKET: ${{ inputs.google-lock-bucket }}
GOOGLE_STORAGE_PLAN_ARTEFACT_BUCKET: ${{ inputs.upload-plan-destination-gcp-bucket }}
AWS_S3_BUCKET: ${{ inputs.upload-plan-destination-s3-bucket }}
Expand Down
56 changes: 53 additions & 3 deletions libs/storage/aws_plan_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,53 @@ type S3Client interface {
DeleteObject(ctx context.Context, params *s3.DeleteObjectInput, optFns ...func(*s3.Options)) (*s3.DeleteObjectOutput, error)
}

type AwsS3EncryptionType string

const (
ServerSideEncryptionAes256 AwsS3EncryptionType = "AES256"
ServerSideEncryptionAwsKms AwsS3EncryptionType = "aws:kms"
)

type PlanStorageAWS struct {
Client S3Client
Bucket string
Context context.Context
Client S3Client
Bucket string
Context context.Context
EncryptionEnabled bool
EncryptionType AwsS3EncryptionType
KMSEncryptionId string
}

func NewAWSPlanStorage(bucketName string, encryptionEnabled bool, encryptionType string, KMSEncryptionId string) (*PlanStorageAWS, error) {
if bucketName == "" {
return nil, fmt.Errorf("AWS_S3_BUCKET is not defined")
}
ctx, client, err := GetAWSStorageClient()
if err != nil {
return nil, fmt.Errorf("could not retrieve aws storage client")
}
planStorage := &PlanStorageAWS{
Context: ctx,
Client: client,
Bucket: bucketName,
}
if encryptionEnabled {
planStorage.EncryptionEnabled = true
if encryptionType == "AES256" {
planStorage.EncryptionType = ServerSideEncryptionAes256
} else if encryptionType == "KMS" {
if KMSEncryptionId == "" {
return nil, fmt.Errorf("KMS encryption requested but no KMS key specified")
}
planStorage.EncryptionType = ServerSideEncryptionAwsKms
planStorage.KMSEncryptionId = KMSEncryptionId
} else {
return nil, fmt.Errorf("unknown encryption type specified for aws plan bucket: %v", encryptionType)
}
}

return planStorage, nil

}
func (psa *PlanStorageAWS) PlanExists(artifactName, storedPlanFilePath string) (bool, error) {
input := &s3.HeadObjectInput{
Bucket: aws.String(psa.Bucket),
Expand Down Expand Up @@ -59,6 +100,15 @@ func (psa *PlanStorageAWS) StorePlanFile(fileContents []byte, artifactName, file
Bucket: aws.String(psa.Bucket),
Key: aws.String(fileName),
}

// support for encryption
if psa.EncryptionEnabled {
input.ServerSideEncryption = types.ServerSideEncryption(psa.EncryptionType)
if psa.EncryptionType == ServerSideEncryptionAwsKms {
input.SSEKMSKeyId = aws.String(psa.KMSEncryptionId)
}
}

_, err := psa.Client.PutObject(psa.Context, input)
if err != nil {
log.Printf("Failed to write file to bucket: %v", err)
Expand Down
18 changes: 7 additions & 11 deletions libs/storage/plan_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,18 +235,14 @@ func NewPlanStorage(ghToken string, ghRepoOwner string, ghRepositoryName string,
Context: ctx,
}
case uploadDestination == "aws":
ctx, client, err := GetAWSStorageClient()
if err != nil {
return nil, fmt.Errorf(fmt.Sprintf("Failed to create AWS storage client: %s", err))
}
bucketName := strings.ToLower(os.Getenv("AWS_S3_BUCKET"))
if bucketName == "" {
return nil, fmt.Errorf("AWS_S3_BUCKET is not defined")
}
planStorage = &PlanStorageAWS{
Context: ctx,
Client: client,
Bucket: bucketName,
encryptionEnabled := os.Getenv("PLAN_UPLOAD_S3_ENCRYPTION_ENABLED") == "true"
encryptionType := os.Getenv("PLAN_UPLOAD_S3_ENCRYPTION_TYPE")
encryptionKmsId := os.Getenv("PLAN_UPLOAD_S3_ENCRYPTION_KMS_ID")
var err error
planStorage, err = NewAWSPlanStorage(bucketName, encryptionEnabled, encryptionType, encryptionKmsId)
if err != nil {
return nil, fmt.Errorf("error while creating AWS plan storage: %v", err)
}
case uploadDestination == "gitlab":
//TODO implement me
Expand Down

0 comments on commit ba40140

Please sign in to comment.