From 916d68dd00d2e67f19bca037a87d1f62cf104230 Mon Sep 17 00:00:00 2001 From: ace-n Date: Fri, 3 Apr 2020 16:02:50 -0700 Subject: [PATCH 1/5] Add GCF bearer auth sample --- functions/security/index.js | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 functions/security/index.js diff --git a/functions/security/index.js b/functions/security/index.js new file mode 100644 index 0000000000..4c0179f5aa --- /dev/null +++ b/functions/security/index.js @@ -0,0 +1,52 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +// [START functions_bearer_token] +const {get} = require('axios'); + +// TODO: set these values +const REGION = 'us-central1'; +const PROJECT_ID = 'nodejs-docs-samples'; +const RECEIVING_FUNCTION = 'myFunction'; + +// Constants for setting up metadata server request +// See https://cloud.google.com/compute/docs/instances/verifying-instance-identity#request_signature +const functionURL = `https://${REGION}-${PROJECT_ID}.cloudfunctions.net/${RECEIVING_FUNCTION}`; +const metadataServerURL = + 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='; +const tokenUrl = metadataServerURL + functionURL; + +exports.bearerToken = async (req, res) => { + // Fetch the token + const tokenResponse = await get(tokenUrl, { + headers: { + 'Metadata-Flavor': 'Google', + }, + }); + const token = tokenResponse.data; + + // Provide the token in the request to the receiving function + try { + const functionResponse = await get(functionURL, { + headers: {Authorization: `bearer ${token}`}, + }); + res.status(200).send(functionResponse.data); + } catch (err) { + console.error(err); + res.status(500).send('An error occurred! See logs for more details.'); + } +}; +// [END functions_bearer_token] From 5c10bf13a5a48c8ed97b7951eb9bbed179d99d72 Mon Sep 17 00:00:00 2001 From: ace-n Date: Fri, 3 Apr 2020 16:30:37 -0700 Subject: [PATCH 2/5] Add tests --- functions/security/index.js | 2 +- functions/security/package.json | 27 ++++++++++++ functions/security/test/index.test.js | 59 +++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 functions/security/package.json create mode 100644 functions/security/test/index.test.js diff --git a/functions/security/index.js b/functions/security/index.js index 4c0179f5aa..abf9e82a3f 100644 --- a/functions/security/index.js +++ b/functions/security/index.js @@ -29,7 +29,7 @@ const metadataServerURL = 'http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience='; const tokenUrl = metadataServerURL + functionURL; -exports.bearerToken = async (req, res) => { +exports.callingFunction = async (req, res) => { // Fetch the token const tokenResponse = await get(tokenUrl, { headers: { diff --git a/functions/security/package.json b/functions/security/package.json new file mode 100644 index 0000000000..cead34debc --- /dev/null +++ b/functions/security/package.json @@ -0,0 +1,27 @@ +{ + "name": "nodejs-docs-samples-functions-security", + "version": "0.0.1", + "private": true, + "license": "Apache-2.0", + "author": "Google Inc.", + "repository": { + "type": "git", + "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" + }, + "engines": { + "node": ">=8.0.0" + }, + "scripts": { + "test": "mocha test/*.test.js" + }, + "dependencies": { + "axios": "^0.19.2", + "eslint-plugin-node": "^11.1.0", + "mocha": "^7.1.1" + }, + "devDependencies": { + "assert": "^2.0.0", + "proxyquire": "^2.1.3", + "sinon": "^9.0.1" + } +} diff --git a/functions/security/test/index.test.js b/functions/security/test/index.test.js new file mode 100644 index 0000000000..0b70787aa3 --- /dev/null +++ b/functions/security/test/index.test.js @@ -0,0 +1,59 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +const proxyquire = require('proxyquire').noCallThru(); +const sinon = require('sinon'); +const assert = require('assert'); + +const getSample = () => { + const getMock = sinon + .stub() + .onFirstCall() + .resolves({data: 'some-token'}) + .onSecondCall() + .resolves({data: 'function-response'}); + + const axiosMock = {get: getMock}; + + const resMock = {}; + resMock.status = sinon.stub().returns(resMock); + resMock.send = sinon.stub().returns(resMock); + + return { + sample: proxyquire('../', { + axios: axiosMock, + }), + mocks: { + res: resMock, + axios: axiosMock, + }, + }; +}; + +describe('functions_bearer_token', () => { + it('should run', async () => { + const {sample, mocks} = getSample(); + + await sample.callingFunction(null, mocks.res); + + assert(mocks.axios.get.calledTwice); + assert.deepEqual(mocks.axios.get.firstCall.args[1], { + headers: {'Metadata-Flavor': 'Google'}, + }); + + assert(mocks.res.send.calledWith('function-response')); + }); +}); From b77567de0315790a5f4d2c2af64fa8d861f52056 Mon Sep 17 00:00:00 2001 From: ace-n Date: Fri, 3 Apr 2020 16:33:37 -0700 Subject: [PATCH 3/5] Use default project ID --- functions/security/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/functions/security/index.js b/functions/security/index.js index abf9e82a3f..9f89028805 100644 --- a/functions/security/index.js +++ b/functions/security/index.js @@ -19,7 +19,7 @@ const {get} = require('axios'); // TODO: set these values const REGION = 'us-central1'; -const PROJECT_ID = 'nodejs-docs-samples'; +const PROJECT_ID = 'my-project-id'; const RECEIVING_FUNCTION = 'myFunction'; // Constants for setting up metadata server request From 9fe1b932c61c41da63a9bb4ca9641878b11226c0 Mon Sep 17 00:00:00 2001 From: ace-n Date: Fri, 3 Apr 2020 16:34:45 -0700 Subject: [PATCH 4/5] Add kokoro cfg --- .kokoro/functions/security.cfg | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .kokoro/functions/security.cfg diff --git a/.kokoro/functions/security.cfg b/.kokoro/functions/security.cfg new file mode 100644 index 0000000000..df57560cd0 --- /dev/null +++ b/.kokoro/functions/security.cfg @@ -0,0 +1,13 @@ +# Format: //devtools/kokoro/config/proto/build.proto + +# Set the folder in which the tests are run +env_vars: { + key: "PROJECT" + value: "functions/security" +} + +# Tell the trampoline which build file to use. +env_vars: { + key: "TRAMPOLINE_BUILD_FILE" + value: "github/nodejs-docs-samples/.kokoro/build.sh" +} From 17d14ac155a002a0486c98359d9e4fac2527a64b Mon Sep 17 00:00:00 2001 From: ace-n Date: Fri, 3 Apr 2020 16:43:36 -0700 Subject: [PATCH 5/5] Fix nits --- functions/security/index.js | 2 +- functions/security/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/functions/security/index.js b/functions/security/index.js index 9f89028805..228595923c 100644 --- a/functions/security/index.js +++ b/functions/security/index.js @@ -17,7 +17,7 @@ // [START functions_bearer_token] const {get} = require('axios'); -// TODO: set these values +// TODO(developer): set these values const REGION = 'us-central1'; const PROJECT_ID = 'my-project-id'; const RECEIVING_FUNCTION = 'myFunction'; diff --git a/functions/security/package.json b/functions/security/package.json index cead34debc..7d3ec22a3e 100644 --- a/functions/security/package.json +++ b/functions/security/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "private": true, "license": "Apache-2.0", - "author": "Google Inc.", + "author": "Google LLC", "repository": { "type": "git", "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git"