From 7acc18e21a7911b668e201abc7dfe2acc29087f6 Mon Sep 17 00:00:00 2001 From: therynamo Date: Wed, 3 Nov 2021 14:38:57 -0500 Subject: [PATCH 1/4] feat: Allow SSE on AWS S3 Buckets Signed-off-by: therynamo --- .changeset/orange-cougars-relax.md | 5 +++++ docs/features/techdocs/configuration.md | 5 +++++ .../techdocs-common/src/stages/publish/awsS3.test.ts | 10 ++++++++++ packages/techdocs-common/src/stages/publish/awsS3.ts | 12 +++++++++++- 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 .changeset/orange-cougars-relax.md diff --git a/.changeset/orange-cougars-relax.md b/.changeset/orange-cougars-relax.md new file mode 100644 index 0000000000..2f55e23220 --- /dev/null +++ b/.changeset/orange-cougars-relax.md @@ -0,0 +1,5 @@ +--- +'@backstage/techdocs-common': patch +--- + +Allow aws s3 buckets to pass an sse configuration so they can publish to encrypted buckets diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index fbe9f36540..cfc522adf6 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -106,6 +106,11 @@ techdocs: # This allows providers like LocalStack, Minio and Wasabi (and possibly others) to be used to host tech docs. s3ForcePathStyle: false + # (Optional) AWS Server Side Encryption + # If not set, encrypted buckets will fail to publish. + # https://docs.aws.amazon.com/AmazonS3/latest/userguide/specifying-s3-encryption.html + sse: 'aws:kms' # or AES256 + # Required when techdocs.publisher.type is set to 'azureBlobStorage'. Skip otherwise. azureBlobStorage: diff --git a/packages/techdocs-common/src/stages/publish/awsS3.test.ts b/packages/techdocs-common/src/stages/publish/awsS3.test.ts index 1f7afa0855..ff88f12939 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.test.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.test.ts @@ -45,10 +45,12 @@ const createPublisherFromConfig = ({ bucketName = 'bucketName', bucketRootPath = '/', legacyUseCaseSensitiveTripletPaths = false, + sse, }: { bucketName?: string; bucketRootPath?: string; legacyUseCaseSensitiveTripletPaths?: boolean; + sse?: string; } = {}) => { const mockConfig = new ConfigReader({ techdocs: { @@ -62,6 +64,7 @@ const createPublisherFromConfig = ({ }, bucketName, bucketRootPath, + sse, }, }, legacyUseCaseSensitiveTripletPaths, @@ -171,6 +174,13 @@ describe('AwsS3Publish', () => { expect(await publisher.publish({ entity, directory })).toBeUndefined(); }); + it('should publish a directory when sse is specified', async () => { + const publisher = createPublisherFromConfig({ + sse: 'aws:kms', + }); + expect(await publisher.publish({ entity, directory })).toBeUndefined(); + }); + it('should fail to publish a directory', async () => { const wrongPathToGeneratedDirectory = path.join( rootDir, diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts index 5ebc2aab77..05ce80eaca 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.ts @@ -62,6 +62,7 @@ export class AwsS3Publish implements PublisherBase { private readonly legacyPathCasing: boolean; private readonly logger: Logger; private readonly bucketRootPath: string; + private readonly sse?: 'aws:kms' | 'AES256'; constructor(options: { storageClient: aws.S3; @@ -75,6 +76,7 @@ export class AwsS3Publish implements PublisherBase { this.legacyPathCasing = options.legacyPathCasing; this.logger = options.logger; this.bucketRootPath = options.bucketRootPath; + this.sse = sse; } static fromConfig(config: Config, logger: Logger): PublisherBase { @@ -92,6 +94,11 @@ export class AwsS3Publish implements PublisherBase { config.getOptionalString('techdocs.publisher.awsS3.bucketRootPath') || '', ); + const sse = config.getOptionalString('techdocs.publisher.awsS3.sse') as + | 'aws:kms' + | 'AES256' + | undefined; + // Credentials is an optional config. If missing, the default ways of authenticating AWS SDK V2 will be used. // 1. AWS environment variables // https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-environment.html @@ -138,6 +145,7 @@ export class AwsS3Publish implements PublisherBase { bucketRootPath, legacyPathCasing, logger, + sse, }); } @@ -208,6 +216,7 @@ export class AwsS3Publish implements PublisherBase { async publish({ entity, directory }: PublishRequest): Promise { const useLegacyPathCasing = this.legacyPathCasing; const bucketRootPath = this.bucketRootPath; + const sse = this.sse; // First, try to retrieve a list of all individual files currently existing let existingFiles: string[] = []; @@ -250,7 +259,8 @@ export class AwsS3Publish implements PublisherBase { bucketRootPath, ), Body: fileStream, - }; + ...(sse && { ServerSideEncryption: sse }), + } as aws.S3.PutObjectRequest; return this.storageClient.upload(params).promise(); }, From 16f7180fa2a34cb70925b941b9762e730b50266a Mon Sep 17 00:00:00 2001 From: Theryn Groetken Date: Thu, 4 Nov 2021 06:38:13 -0500 Subject: [PATCH 2/4] Update orange-cougars-relax.md Signed-off-by: therynamo --- .changeset/orange-cougars-relax.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/orange-cougars-relax.md b/.changeset/orange-cougars-relax.md index 2f55e23220..0a13987551 100644 --- a/.changeset/orange-cougars-relax.md +++ b/.changeset/orange-cougars-relax.md @@ -2,4 +2,4 @@ '@backstage/techdocs-common': patch --- -Allow aws s3 buckets to pass an sse configuration so they can publish to encrypted buckets +Allow amazon web services s3 buckets to pass an server side encryption configuration so they can publish to encrypted buckets From 9e64a7ac1e0823fdef7304ce06d9e18960f8dfa7 Mon Sep 17 00:00:00 2001 From: therynamo Date: Mon, 15 Nov 2021 10:51:36 -0600 Subject: [PATCH 3/4] pr suggestions Signed-off-by: therynamo --- ...-cougars-relax.md => techdocs-orange-cougars-relax.md} | 1 + docs/features/techdocs/configuration.md | 1 + plugins/techdocs-backend/config.d.ts | 8 ++++++++ 3 files changed, 10 insertions(+) rename .changeset/{orange-cougars-relax.md => techdocs-orange-cougars-relax.md} (82%) diff --git a/.changeset/orange-cougars-relax.md b/.changeset/techdocs-orange-cougars-relax.md similarity index 82% rename from .changeset/orange-cougars-relax.md rename to .changeset/techdocs-orange-cougars-relax.md index 0a13987551..3776c9ea15 100644 --- a/.changeset/orange-cougars-relax.md +++ b/.changeset/techdocs-orange-cougars-relax.md @@ -1,5 +1,6 @@ --- '@backstage/techdocs-common': patch +'@backstage/techdocs-backend': patch --- Allow amazon web services s3 buckets to pass an server side encryption configuration so they can publish to encrypted buckets diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index cfc522adf6..61d95f55c0 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -107,6 +107,7 @@ techdocs: s3ForcePathStyle: false # (Optional) AWS Server Side Encryption + # Defaults to undefined. # If not set, encrypted buckets will fail to publish. # https://docs.aws.amazon.com/AmazonS3/latest/userguide/specifying-s3-encryption.html sse: 'aws:kms' # or AES256 diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index 0023a4b757..d8049daec9 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -121,6 +121,14 @@ export interface Config { * @visibility backend */ s3ForcePathStyle?: boolean; + + /** + * (Optional) AWS Server Side Encryption + * Defaults to undefined. + * If not set, encrypted buckets will fail to publish. + * https://docs.aws.amazon.com/AmazonS3/latest/userguide/specifying-s3-encryption.html + */ + sse: 'aws:kms' | 'AES256'; }; } | { From b0c7748ab5cc2d124dd03dd87155d19c588f128f Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Tue, 16 Nov 2021 10:34:56 +0100 Subject: [PATCH 4/4] Ensure sse config is optional; pass through sse from constructor. Signed-off-by: Eric Peterson --- packages/techdocs-common/src/stages/publish/awsS3.ts | 3 ++- plugins/techdocs-backend/config.d.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/techdocs-common/src/stages/publish/awsS3.ts b/packages/techdocs-common/src/stages/publish/awsS3.ts index 05ce80eaca..abfa8ddd24 100644 --- a/packages/techdocs-common/src/stages/publish/awsS3.ts +++ b/packages/techdocs-common/src/stages/publish/awsS3.ts @@ -70,13 +70,14 @@ export class AwsS3Publish implements PublisherBase { legacyPathCasing: boolean; logger: Logger; bucketRootPath: string; + sse?: 'aws:kms' | 'AES256'; }) { this.storageClient = options.storageClient; this.bucketName = options.bucketName; this.legacyPathCasing = options.legacyPathCasing; this.logger = options.logger; this.bucketRootPath = options.bucketRootPath; - this.sse = sse; + this.sse = options.sse; } static fromConfig(config: Config, logger: Logger): PublisherBase { diff --git a/plugins/techdocs-backend/config.d.ts b/plugins/techdocs-backend/config.d.ts index d8049daec9..da3cd34830 100644 --- a/plugins/techdocs-backend/config.d.ts +++ b/plugins/techdocs-backend/config.d.ts @@ -128,7 +128,7 @@ export interface Config { * If not set, encrypted buckets will fail to publish. * https://docs.aws.amazon.com/AmazonS3/latest/userguide/specifying-s3-encryption.html */ - sse: 'aws:kms' | 'AES256'; + sse?: 'aws:kms' | 'AES256'; }; } | {