feat: Allow SSE on AWS S3 Buckets

Signed-off-by: therynamo <theryn.groetken@gemini.com>
This commit is contained in:
therynamo
2021-11-03 14:38:57 -05:00
parent 3e6762ba3f
commit 7acc18e21a
4 changed files with 31 additions and 1 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/techdocs-common': patch
---
Allow aws s3 buckets to pass an sse configuration so they can publish to encrypted buckets
+5
View File
@@ -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:
@@ -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,
@@ -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<void> {
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();
},