From faa30e153f29dfd8ada86598a1a7433155c8b996 Mon Sep 17 00:00:00 2001 From: Thomas Bouldin Date: Mon, 29 Nov 2021 15:31:56 -0800 Subject: [PATCH] Force HTTPS in newly created v1 functions --- CHANGELOG.md | 1 + src/deploy/functions/release/fabricator.ts | 6 ++++++ .../deploy/functions/release/fabricator.spec.ts | 14 ++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d739035cfcd..4e712e6a008 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,3 @@ - Corrects a bug where containers in Artifact Registry would not be deleted if a function has an upper case character in its name - Fixes issue where providing the `--project` flag during `init` would not be recognized with a default project already set. (#3870) +- New HTTPS functions only allow secure traffic. diff --git a/src/deploy/functions/release/fabricator.ts b/src/deploy/functions/release/fabricator.ts index d3f46d3e036..654ddefe9dc 100644 --- a/src/deploy/functions/release/fabricator.ts +++ b/src/deploy/functions/release/fabricator.ts @@ -205,6 +205,12 @@ export class Fabricator { throw new Error("Precondition failed"); } const apiFunction = gcf.functionFromEndpoint(endpoint, this.sourceUrl); + // As a general security practice and way to smooth out the upgrade path + // for GCF gen 2, we are enforcing that all new GCFv1 deploys will require + // HTTPS + if (apiFunction.httpsTrigger) { + apiFunction.httpsTrigger.securityLevel = "SECURE_ALWAYS"; + } apiFunction.sourceToken = await scraper.tokenPromise(); const resultFunction = await this.functionExecutor .run(async () => { diff --git a/src/test/deploy/functions/release/fabricator.spec.ts b/src/test/deploy/functions/release/fabricator.spec.ts index b40c5b9fff8..1dcf479cff4 100644 --- a/src/test/deploy/functions/release/fabricator.spec.ts +++ b/src/test/deploy/functions/release/fabricator.spec.ts @@ -136,6 +136,20 @@ describe("Fabricator", () => { ).to.be.rejectedWith(reporter.DeploymentError, "set invoker"); }); + it("enforces SECURE_ALWAYS HTTPS policies", async () => { + gcf.createFunction.resolves({ name: "op", type: "create", done: false }); + poller.pollOperation.resolves(); + gcf.setInvokerCreate.resolves(); + const ep = endpoint(); + + await fab.createV1Function(ep, new scraper.SourceTokenScraper()); + expect(gcf.createFunction).to.have.been.calledWithMatch({ + httpsTrigger: { + securityLevel: "SECURE_ALWAYS", + }, + }); + }); + it("sets invoker by default", async () => { gcf.createFunction.resolves({ name: "op", type: "create", done: false }); poller.pollOperation.resolves();