diff --git a/CHANGELOG.md b/CHANGELOG.md index e69de29bb..ecd0a47c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -0,0 +1 @@ +- Add new runtime option for setting secrets. diff --git a/spec/v1/cloud-functions.spec.ts b/spec/v1/cloud-functions.spec.ts index c894bfa23..5dd0a8941 100644 --- a/spec/v1/cloud-functions.spec.ts +++ b/spec/v1/cloud-functions.spec.ts @@ -107,6 +107,7 @@ describe('makeCloudFunction', () => { regions: ['us-central1'], memory: '128MB', serviceAccount: 'foo@google.com', + secrets: ['MY_SECRET'], }, }); @@ -123,6 +124,7 @@ describe('makeCloudFunction', () => { }, retry: false, }, + secretEnvironmentVariables: [{ secret: 'MY_SECRET', key: 'MY_SECRET' }], labels: {}, }); }); diff --git a/spec/v1/function-builder.spec.ts b/spec/v1/function-builder.spec.ts index 13d4daa06..8e01cd87a 100644 --- a/spec/v1/function-builder.spec.ts +++ b/spec/v1/function-builder.spec.ts @@ -472,11 +472,45 @@ describe('FunctionBuilder', () => { ).to.throw(); }); - it('', () => { + it('should throw an error if private identifier is in the invoker array', () => { expect(() => functions.runWith({ invoker: ['service-account1', 'private', 'service-account2'], }) ).to.throw(); }); + + it('should allow valid secret config expressed using short form', () => { + const secrets = ['API_KEY']; + const fn = functions + .runWith({ secrets }) + .auth.user() + .onCreate((user) => user); + + expect(fn.__trigger.secrets).to.deep.equal(secrets); + }); + + it('should throw error given secrets expressed with full resource name', () => { + expect(() => + functions.runWith({ + secrets: ['projects/my-project/secrets/API_KEY'], + }) + ).to.throw(); + }); + + it('should throw error given invalid secret config', () => { + expect(() => + functions.runWith({ + secrets: ['ABC/efg'], + }) + ).to.throw(); + }); + + it('should throw error given invalid secret with versions', () => { + expect(() => + functions.runWith({ + secrets: ['ABC@3'], + }) + ).to.throw(); + }); }); diff --git a/src/cloud-functions.ts b/src/cloud-functions.ts index d07676432..ffe94e031 100644 --- a/src/cloud-functions.ts +++ b/src/cloud-functions.ts @@ -281,6 +281,7 @@ export interface TriggerAnnotated { vpcConnectorEgressSettings?: string; serviceAccountEmail?: string; ingressSettings?: string; + secrets?: string[]; }; } @@ -552,7 +553,8 @@ export function optionsToTrigger(options: DeploymentOptions) { 'ingressSettings', 'vpcConnectorEgressSettings', 'vpcConnector', - 'labels' + 'labels', + 'secrets' ); convertIfPresent( trigger, @@ -620,6 +622,13 @@ export function optionsToEndpoint( 'serviceAccount', (sa) => sa ); + convertIfPresent( + endpoint, + options, + 'secretEnvironmentVariables', + 'secrets', + (secrets) => secrets.map((secret) => ({ secret, key: secret })) + ); if (options?.vpcConnector) { endpoint.vpc = { connector: options.vpcConnector }; convertIfPresent( diff --git a/src/common/manifest.ts b/src/common/manifest.ts new file mode 100644 index 000000000..e69de29bb diff --git a/src/function-builder.ts b/src/function-builder.ts index ef6f1ad16..cf52bfb56 100644 --- a/src/function-builder.ts +++ b/src/function-builder.ts @@ -229,6 +229,18 @@ function assertRuntimeOptionsValid(runtimeOptions: RuntimeOptions): boolean { } } + if (runtimeOptions.secrets !== undefined) { + const invalidSecrets = runtimeOptions.secrets.filter( + (s) => !/^[A-Za-z\d\-_]+$/.test(s) + ); + if (invalidSecrets.length > 0) { + throw new Error( + `Invalid secrets: ${invalidSecrets.join(',')}. ` + + 'Secret must be configured using the resource id (e.g. API_KEY)' + ); + } + } + return true; } diff --git a/src/function-configuration.ts b/src/function-configuration.ts index 5aa6177fd..73cc64eac 100644 --- a/src/function-configuration.ts +++ b/src/function-configuration.ts @@ -165,6 +165,11 @@ export interface RuntimeOptions { * Allow requests with invalid App Check tokens on callable functions. */ allowInvalidAppCheckToken?: boolean; + + /* + * Secrets to bind to a function instance. + */ + secrets?: string[]; } export interface DeploymentOptions extends RuntimeOptions { diff --git a/src/runtime/manifest.ts b/src/runtime/manifest.ts index 656a0c5d1..aaaf87761 100644 --- a/src/runtime/manifest.ts +++ b/src/runtime/manifest.ts @@ -39,6 +39,7 @@ export interface ManifestEndpoint { labels?: Record; ingressSettings?: string; environmentVariables?: Record; + secretEnvironmentVariables?: { key: string; secret?: string }[]; httpsTrigger?: { invoker?: string[];