From 1ef5d0f13c3913f387e97eb9466cad69ebd9519c Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Sat, 9 Jan 2021 16:07:39 +0100 Subject: [PATCH 1/7] TechDocs/GCS: Enable authentication using environemnt variables GOOGLE_APPLICATION_CREDENTIALS is the environment variable used by the client. Compute Engine, Google Kubernetes Engine, App Engine, Cloud Run, and Cloud Functions automatically provide a default service account and set this env variable. https://cloud.google.com/docs/authentication/production --- .../src/stages/publish/googleStorage.ts | 71 ++++++++++--------- .../src/stages/publish/publish.ts | 2 +- plugins/techdocs/config.d.ts | 8 ++- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index b33e2bfbe0..20c1e96df9 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -27,57 +27,60 @@ import { getHeadersForFileExtension, getFileTreeRecursively } from './helpers'; import { PublisherBase, PublishRequest } from './types'; export class GoogleGCSPublish implements PublisherBase { - static fromConfig(config: Config, logger: Logger): PublisherBase { - let credentials = ''; - let projectId = ''; + static async fromConfig( + config: Config, + logger: Logger, + ): Promise { let bucketName = ''; try { - credentials = config.getString( - 'techdocs.publisher.googleGcs.credentials', - ); - projectId = config.getString('techdocs.publisher.googleGcs.projectId'); bucketName = config.getString('techdocs.publisher.googleGcs.bucketName'); } catch (error) { throw new Error( "Since techdocs.publisher.type is set to 'googleGcs' in your app config, " + - 'credentials, projectId and bucketName are required in techdocs.publisher.googleGcs ' + - 'required to authenticate with Google Cloud Storage.', + 'techdocs.publisher.googleGcs.bucketName is required.', ); } + // Credentials is an optional config. If missing, default GCS environment variables will be used. + // Read more here https://cloud.google.com/docs/authentication/production + const credentials = config.getOptionalString( + 'techdocs.publisher.googleGcs.credentials', + ); let credentialsJson = {}; - try { - credentialsJson = JSON.parse(credentials); - } catch (err) { - throw new Error( - 'Error in parsing techdocs.publisher.googleGcs.credentials config to JSON.', - ); + if (credentials) { + try { + credentialsJson = JSON.parse(credentials); + } catch (err) { + throw new Error( + 'Error in parsing techdocs.publisher.googleGcs.credentials config to JSON.', + ); + } } + const projectId = config.getOptionalString( + 'techdocs.publisher.googleGcs.projectId', + ); const storageClient = new Storage({ - credentials: credentialsJson, - projectId: projectId, + ...(credentials && { + credentials: credentialsJson, + }), + ...(projectId && { projectId }), }); // Check if the defined bucket exists. Being able to connect means the configuration is good // and the storage client will work. - storageClient - .bucket(bucketName) - .getMetadata() - .then(() => { - logger.info( - `Successfully connected to the GCS bucket ${bucketName} in the GCP project ${projectId}.`, - ); - }) - .catch(reason => { - logger.error( - `Could not retrieve metadata about the GCS bucket ${bucketName} in the GCP project ${projectId}. ` + - 'Make sure the GCP project and the bucket exists and the access key located at the path ' + - "techdocs.publisher.googleGcs.credentials defined in app config has the role 'Storage Object Creator'. " + - 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', - ); - throw new Error(`from GCS client library: ${reason.message}`); - }); + try { + await storageClient.bucket(bucketName).getMetadata(); + logger.info(`Successfully connected to the GCS bucket ${bucketName}.`); + } catch (err) { + logger.error( + `Could not retrieve metadata about the GCS bucket ${bucketName}. ` + + 'Make sure the bucket exists. Also make sure that authentication is setup either by explicitly defining ' + + 'techdocs.publisher.googleGcs.credentials in app config or by using environment variables' + + 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', + ); + throw new Error(err.message); + } return new GoogleGCSPublish(storageClient, bucketName, logger); } diff --git a/packages/techdocs-common/src/stages/publish/publish.ts b/packages/techdocs-common/src/stages/publish/publish.ts index caaf8a4cec..82232c2fd1 100644 --- a/packages/techdocs-common/src/stages/publish/publish.ts +++ b/packages/techdocs-common/src/stages/publish/publish.ts @@ -43,7 +43,7 @@ export class Publisher { switch (publisherType) { case 'googleGcs': logger.info('Creating Google Storage Bucket publisher for TechDocs'); - return GoogleGCSPublish.fromConfig(config, logger); + return await GoogleGCSPublish.fromConfig(config, logger); case 'awsS3': logger.info('Creating AWS S3 Bucket publisher for TechDocs'); return AwsS3Publish.fromConfig(config, logger); diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index ad2daeb9a3..f1846a1e0e 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -123,17 +123,19 @@ export interface Config { */ googleGcs?: { /** - * API key used to write to a storage bucket. + * (Optional) API key used to write to a storage bucket. + * If not set, environment variables will be used to authenticate. + * Read more: https://cloud.google.com/docs/authentication/production * attr: 'credentials' - accepts a string value * @visibility secret */ - credentials: string; + credentials?: string; /** * GCP Project ID where the Cloud Storage Bucket is hosted. * attr: 'projectId' - accepts a string value * @visibility secret */ - projectId: string; + projectId?: string; /** * Cloud Storage Bucket Name * attr: 'bucketName' - accepts a string value From e7954559abb3ab57b75cb694e5897f784fe8d21c Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Sat, 9 Jan 2021 16:29:42 +0100 Subject: [PATCH 2/7] TechDocs/GCS: Remove projectId since it is not needed I initially thought the GCS Nodejs client would make use of it, since it asked for it in the contructor. However, we may not need them at all. Buckets are gloablly unique anyway. --- .../__mocks__/@google-cloud/storage.ts | 3 --- .../src/stages/publish/googleStorage.test.ts | 5 ++--- .../src/stages/publish/googleStorage.ts | 4 ---- .../src/stages/publish/publish.test.ts | 1 - plugins/techdocs/config.d.ts | 18 ++++++------------ 5 files changed, 8 insertions(+), 23 deletions(-) diff --git a/packages/techdocs-common/__mocks__/@google-cloud/storage.ts b/packages/techdocs-common/__mocks__/@google-cloud/storage.ts index e95cee11d0..b84018c089 100644 --- a/packages/techdocs-common/__mocks__/@google-cloud/storage.ts +++ b/packages/techdocs-common/__mocks__/@google-cloud/storage.ts @@ -14,7 +14,6 @@ * limitations under the License. */ type storageOptions = { - projectId?: string; keyFilename?: string; }; @@ -39,11 +38,9 @@ class Bucket { } export class Storage { - private readonly projectId; private readonly keyFilename; constructor(options: storageOptions) { - this.projectId = options.projectId; this.keyFilename = options.keyFilename; } diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts index 43375b72d0..f8fb00647c 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.test.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.test.ts @@ -37,7 +37,7 @@ jest.spyOn(logger, 'info').mockReturnValue(logger); let publisher: PublisherBase; -beforeEach(() => { +beforeEach(async () => { const mockConfig = new ConfigReader({ techdocs: { requestUrl: 'http://localhost:7000', @@ -45,14 +45,13 @@ beforeEach(() => { type: 'googleGcs', googleGcs: { credentials: '{}', - projectId: 'gcp-project-id', bucketName: 'bucketName', }, }, }, }); - publisher = GoogleGCSPublish.fromConfig(mockConfig, logger); + publisher = await GoogleGCSPublish.fromConfig(mockConfig, logger); }); describe('GoogleGCSPublish', () => { diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index 20c1e96df9..ffed59b8ba 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -56,15 +56,11 @@ export class GoogleGCSPublish implements PublisherBase { ); } } - const projectId = config.getOptionalString( - 'techdocs.publisher.googleGcs.projectId', - ); const storageClient = new Storage({ ...(credentials && { credentials: credentialsJson, }), - ...(projectId && { projectId }), }); // Check if the defined bucket exists. Being able to connect means the configuration is good diff --git a/packages/techdocs-common/src/stages/publish/publish.test.ts b/packages/techdocs-common/src/stages/publish/publish.test.ts index d7cc257b89..89f2c0ffdd 100644 --- a/packages/techdocs-common/src/stages/publish/publish.test.ts +++ b/packages/techdocs-common/src/stages/publish/publish.test.ts @@ -69,7 +69,6 @@ describe('Publisher', () => { type: 'googleGcs', googleGcs: { credentials: '{}', - projectId: 'gcp-project-id', bucketName: 'bucketName', }, }, diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index f1846a1e0e..49f9d396cb 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -122,6 +122,12 @@ export interface Config { * googleGcs required when 'type' is set to googleGcs */ googleGcs?: { + /** + * Cloud Storage Bucket Name + * attr: 'bucketName' - accepts a string value + * @visibility secret + */ + bucketName: string; /** * (Optional) API key used to write to a storage bucket. * If not set, environment variables will be used to authenticate. @@ -130,18 +136,6 @@ export interface Config { * @visibility secret */ credentials?: string; - /** - * GCP Project ID where the Cloud Storage Bucket is hosted. - * attr: 'projectId' - accepts a string value - * @visibility secret - */ - projectId?: string; - /** - * Cloud Storage Bucket Name - * attr: 'bucketName' - accepts a string value - * @visibility secret - */ - bucketName: string; }; }; }; From ba86ff2d8cd95f2e7d8bad172ed8174263f0f28f Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Sat, 9 Jan 2021 16:30:08 +0100 Subject: [PATCH 3/7] TechDocs/GCS: Update docs regarding credentials and removed projectId key --- docs/features/techdocs/configuration.md | 13 ++-- docs/features/techdocs/using-cloud-storage.md | 70 +++++++++++-------- 2 files changed, 45 insertions(+), 38 deletions(-) diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index 7a0a4dbbbf..8c1a024f33 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -54,16 +54,15 @@ techdocs: # Required when techdocs.publisher.type is set to 'googleGcs'. Skip otherwise. googleGcs: - # An API key is required to write to a storage bucket. + # (Required) Cloud Storage Bucket Name + bucketName: 'techdocs-storage' + + # (Optional) An API key is required to write to a storage bucket. + # If missing, GOOGLE_APPLICATION_CREDENTIALS environment variable will be used. + # https://cloud.google.com/docs/authentication/production credentials: $file: '/path/to/google_application_credentials.json' - # Your GCP Project ID where the Cloud Storage Bucket is hosted. - projectId: 'gcp-project-id' - - # Cloud Storage Bucket Name - bucketName: 'techdocs-storage' - # Required when techdocs.publisher.type is set to 'awsS3'. Skip otherwise. awsS3: diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index c05346ca4a..42e8d83f29 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -30,20 +30,34 @@ techdocs: type: 'googleGcs' ``` -**2. GCP (Google Cloud Platform) Project** +**2. GCS Bucket** -Create or choose a dedicated GCP project. Set -`techdocs.publisher.googleGcs.projectId` to the project ID. +Create a dedicated Google Cloud Storage bucket for TechDocs sites. +techdocs-backend will publish documentation to this bucket. TechDocs will fetch +files from here to serve documentation in Backstage. Note that the bucket names +are globally unique. + +Set the name of the bucket to `techdocs.publisher.googleGcs.bucketName`. ```yaml techdocs: publisher: type: 'googleGcs' - googleGcs: - projectId: 'gcp-project-id' + googleGcs: + bucketName: 'name-of-techdocs-storage-bucket' ``` -**3. Service account API key** +**3a. (Recommended) Authentication using environment variable** + +The GCS Node.js client will automatically use the environment variable +`GOOGLE_APPLICATION_CREDENTIALS` to authenticate with Google Cloud. It might +already be set in Compute Engine, Google Kubernetes Engine, etc. Read +https://cloud.google.com/docs/authentication/production for more details. + +**3b. Authentication using app-config.yaml** + +If you do not prefer (3a) and optionally like to use a service account, you can +follow these steps. Create a new Service Account and a key associated with it. In roles of the service account, use "Storage Admin". @@ -65,34 +79,29 @@ techdocs: publisher: type: 'googleGcs' googleGcs: - projectId: 'gcp-project-id' + bucketName: 'name-of-techdocs-storage-bucket' credentials: $file: '/path/to/google_application_credentials.json' ``` -**4. GCS Bucket** - -Create a dedicated bucket for TechDocs sites. techdocs-backend will publish -documentation to this bucket. TechDocs will fetch files from here to serve -documentation in Backstage. - -Set the name of the bucket to `techdocs.publisher.googleGcs.bucketName`. +Note: If you are finding it difficult to make the file +`google_application_credentials.json` available on a server, you could use the +file's content and set as an environment variable. And then use ```yaml techdocs: publisher: type: 'googleGcs' googleGcs: - projectId: 'gcp-project-id' - credentials: - $file: '/path/to/google_application_credentials.json' bucketName: 'name-of-techdocs-storage-bucket' + credentials: + $env: TECHDOCS_GCS_CREDENTIALS ``` -**5. That's it!** +**4. That's it!** Your Backstage app is now ready to use Google Cloud Storage for TechDocs, to -store the static generated documentation files. +store and read the static generated documentation files. ## Configuring AWS S3 Bucket with TechDocs @@ -113,9 +122,8 @@ techdocs: **2. AWS Policies** AWS Policies lets you **control access** to Amazon Web Services (AWS) products -and resources. -Here we will use a user policy **and** a bucket policy to show you the different -possibilities you have but you can use only one. +and resources. Here we will use a user policy **and** a bucket policy to show +you the different possibilities you have but you can use only one. AWS S3 @@ -135,9 +143,9 @@ and the **user** policy. **2.1.1 Create an Admin user** (if you don't have one yet) Create an **administrator user** account `ADMIN_USER` and grant it administrator -privileges by attaching a user policy giving the account **full access**. -Note down the Admin User credentials and IAM User Sign-In URL as you will need -to use this information in the next step. +privileges by attaching a user policy giving the account **full access**. Note +down the Admin User credentials and IAM User Sign-In URL as you will need to use +this information in the next step. **2.1.2 Create an AWS S3 Bucket** @@ -171,9 +179,9 @@ In the IAM console, do the following: **2.2 Attach policies** -Remember that you can use Bucket policy **or** User policy. -Just make sure that you grant all the permissions to the TechDocs user: -`3:PutObject`, `s3:GetObject`, `s3:ListBucket` and `s3:GetBucketLocation`. +Remember that you can use Bucket policy **or** User policy. Just make sure that +you grant all the permissions to the TechDocs user: `3:PutObject`, +`s3:GetObject`, `s3:ListBucket` and `s3:GetBucketLocation`. **2.2.1 Create the bucket policy** @@ -209,9 +217,9 @@ section: - The first statement grants **TechDocs User** the bucket operation permissions `s3:GetBucketLocation` and `s3:ListBucket` which are permissions required by the console. -- The second statement grants the `s3:GetObject` permission. - (**NOTE :** if you do not use the user policy defined below you must also add - the `s3:PutObject` permission to allow the TechDocs user to add objects.) +- The second statement grants the `s3:GetObject` permission. (**NOTE :** if you + do not use the user policy defined below you must also add the `s3:PutObject` + permission to allow the TechDocs user to add objects.) **2.2.2 Create the user policy** From dbe4450c353b23e468fa1e5a0c28444f12c096c3 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Sat, 9 Jan 2021 16:48:30 +0100 Subject: [PATCH 4/7] TechDocs: Add changeset for improved GCS authentication --- .changeset/heavy-owls-float.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/heavy-owls-float.md diff --git a/.changeset/heavy-owls-float.md b/.changeset/heavy-owls-float.md new file mode 100644 index 0000000000..1b0bc9f016 --- /dev/null +++ b/.changeset/heavy-owls-float.md @@ -0,0 +1,10 @@ +--- +'@backstage/techdocs-common': patch +'@backstage/plugin-techdocs': patch +--- + +Google Cloud authentication in TechDocs has been improved. https://github.com/backstage/backstage/pull/3981 + +`techdocs.publisher.googleGcs.credentials` is now optional. If it is missing, `GOOGLE_APPLICATION_CREDENTIALS` +environment variable (and some other methods) will be used to authenticate. +Read more here https://cloud.google.com/docs/authentication/production From bcc27a495d33e1e29a1e9f8a43fef4176d874232 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 11 Jan 2021 14:04:17 +0100 Subject: [PATCH 5/7] TechDocs: doc improvements Co-authored-by: Emma Indal --- docs/features/techdocs/using-cloud-storage.md | 2 +- plugins/techdocs/config.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index 42e8d83f29..b06f5c00a8 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -95,7 +95,7 @@ techdocs: googleGcs: bucketName: 'name-of-techdocs-storage-bucket' credentials: - $env: TECHDOCS_GCS_CREDENTIALS + $env: GOOGLE_APPLICATION_CREDENTIALS ``` **4. That's it!** diff --git a/plugins/techdocs/config.d.ts b/plugins/techdocs/config.d.ts index 49f9d396cb..fc05d79339 100644 --- a/plugins/techdocs/config.d.ts +++ b/plugins/techdocs/config.d.ts @@ -123,7 +123,7 @@ export interface Config { */ googleGcs?: { /** - * Cloud Storage Bucket Name + * (Required) Cloud Storage Bucket Name * attr: 'bucketName' - accepts a string value * @visibility secret */ From 97716f2b0416e5307b54f4c66a3065843fee7cfb Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 11 Jan 2021 20:50:20 +0100 Subject: [PATCH 6/7] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw --- .changeset/heavy-owls-float.md | 2 +- docs/features/techdocs/using-cloud-storage.md | 2 +- packages/techdocs-common/src/stages/publish/googleStorage.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.changeset/heavy-owls-float.md b/.changeset/heavy-owls-float.md index 1b0bc9f016..1997e64d72 100644 --- a/.changeset/heavy-owls-float.md +++ b/.changeset/heavy-owls-float.md @@ -3,7 +3,7 @@ '@backstage/plugin-techdocs': patch --- -Google Cloud authentication in TechDocs has been improved. https://github.com/backstage/backstage/pull/3981 +Google Cloud authentication in TechDocs has been improved. `techdocs.publisher.googleGcs.credentials` is now optional. If it is missing, `GOOGLE_APPLICATION_CREDENTIALS` environment variable (and some other methods) will be used to authenticate. diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index b06f5c00a8..7be977887b 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -180,7 +180,7 @@ In the IAM console, do the following: **2.2 Attach policies** Remember that you can use Bucket policy **or** User policy. Just make sure that -you grant all the permissions to the TechDocs user: `3:PutObject`, +you grant all the permissions to the TechDocs user: `s3:PutObject`, `s3:GetObject`, `s3:ListBucket` and `s3:GetBucketLocation`. **2.2.1 Create the bucket policy** diff --git a/packages/techdocs-common/src/stages/publish/googleStorage.ts b/packages/techdocs-common/src/stages/publish/googleStorage.ts index ffed59b8ba..6dd7e12aea 100644 --- a/packages/techdocs-common/src/stages/publish/googleStorage.ts +++ b/packages/techdocs-common/src/stages/publish/googleStorage.ts @@ -72,7 +72,7 @@ export class GoogleGCSPublish implements PublisherBase { logger.error( `Could not retrieve metadata about the GCS bucket ${bucketName}. ` + 'Make sure the bucket exists. Also make sure that authentication is setup either by explicitly defining ' + - 'techdocs.publisher.googleGcs.credentials in app config or by using environment variables' + + 'techdocs.publisher.googleGcs.credentials in app config or by using environment variables. ' + 'Refer to https://backstage.io/docs/features/techdocs/using-cloud-storage', ); throw new Error(err.message); From 7ed480774878ecf0ac7cd3ec1526c2ebad88cf1b Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 11 Jan 2021 21:05:23 +0100 Subject: [PATCH 7/7] 1. docs: Rephrase setting the config 2. Update changeset with info about removing projectId from googleGcs config --- .changeset/heavy-owls-float.md | 8 +++++--- docs/features/techdocs/using-cloud-storage.md | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.changeset/heavy-owls-float.md b/.changeset/heavy-owls-float.md index 1997e64d72..274876e723 100644 --- a/.changeset/heavy-owls-float.md +++ b/.changeset/heavy-owls-float.md @@ -5,6 +5,8 @@ Google Cloud authentication in TechDocs has been improved. -`techdocs.publisher.googleGcs.credentials` is now optional. If it is missing, `GOOGLE_APPLICATION_CREDENTIALS` -environment variable (and some other methods) will be used to authenticate. -Read more here https://cloud.google.com/docs/authentication/production +1. `techdocs.publisher.googleGcs.credentials` is now optional. If it is missing, `GOOGLE_APPLICATION_CREDENTIALS` + environment variable (and some other methods) will be used to authenticate. + Read more here https://cloud.google.com/docs/authentication/production + +2. `techdocs.publisher.googleGcs.projectId` is no longer used. You can remove it from your `app-config.yaml`. diff --git a/docs/features/techdocs/using-cloud-storage.md b/docs/features/techdocs/using-cloud-storage.md index 7be977887b..474d9d64e6 100644 --- a/docs/features/techdocs/using-cloud-storage.md +++ b/docs/features/techdocs/using-cloud-storage.md @@ -37,7 +37,8 @@ techdocs-backend will publish documentation to this bucket. TechDocs will fetch files from here to serve documentation in Backstage. Note that the bucket names are globally unique. -Set the name of the bucket to `techdocs.publisher.googleGcs.bucketName`. +Set the config `techdocs.publisher.googleGcs.bucketName` in your +`app-config.yaml` to the name of the bucket you just created. ```yaml techdocs: