From 43377ac7af1ece14b82b053b504449f257d11af6 Mon Sep 17 00:00:00 2001 From: Daniel Bankhead Date: Thu, 29 Jun 2023 07:20:27 -0700 Subject: [PATCH] feat: Utilize `gcp-metadata`'s GCP Residency Check (#1513) * feat: utilize `gcp-residency` check Removes 1 network check for workloads running on GCP * test: Update tests for gcp residency detection * refactor: streamline logic and update documentation * chore: stash * chore: Update `gcp-metadata` * refactor: use `getGCPResidency` * test: Dedup gcp-metadata tests * fix: await --- package.json | 2 +- src/auth/googleauth.ts | 7 ++++- test/test.googleauth.ts | 64 +++++------------------------------------ 3 files changed, 14 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index 88c701f0..bf2331bd 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "ecdsa-sig-formatter": "^1.0.11", "fast-text-encoding": "^1.0.0", "gaxios": "^5.0.0", - "gcp-metadata": "^5.2.0", + "gcp-metadata": "^5.3.0", "gtoken": "^6.1.0", "jws": "^4.0.0", "lru-cache": "^6.0.0" diff --git a/src/auth/googleauth.ts b/src/auth/googleauth.ts index 77566cfb..ca31fb13 100644 --- a/src/auth/googleauth.ts +++ b/src/auth/googleauth.ts @@ -396,13 +396,18 @@ export class GoogleAuth { /** * Determines whether the auth layer is running on Google Compute Engine. + * Checks for GCP Residency, then fallback to checking if metadata server + * is available. + * * @returns A promise that resolves with the boolean. * @api private */ async _checkIsGCE() { if (this.checkIsGCE === undefined) { - this.checkIsGCE = await gcpMetadata.isAvailable(); + this.checkIsGCE = + gcpMetadata.getGCPResidency() || (await gcpMetadata.isAvailable()); } + return this.checkIsGCE; } diff --git a/test/test.googleauth.ts b/test/test.googleauth.ts index 04be4314..eca30109 100644 --- a/test/test.googleauth.ts +++ b/test/test.googleauth.ts @@ -25,6 +25,7 @@ import { SECONDARY_HOST_ADDRESS, resetIsAvailableCache, } from 'gcp-metadata'; +import * as gcpMetadata from 'gcp-metadata'; import * as nock from 'nock'; import * as os from 'os'; import * as path from 'path'; @@ -1137,66 +1138,15 @@ describe('googleauth', () => { assert.strictEqual(undefined, client.scope); }); - it('_checkIsGCE should set the _isGCE flag when running on GCE', async () => { - assert.notStrictEqual(true, auth.isGCE); - const scope = nockIsGCE(); - await auth._checkIsGCE(); - assert.strictEqual(true, auth.isGCE); - scope.done(); - }); - - it('_checkIsGCE should not set the _isGCE flag when not running on GCE', async () => { - const scope = nockNotGCE(); - assert.notStrictEqual(true, auth.isGCE); - await auth._checkIsGCE(); - assert.strictEqual(false as boolean, auth.isGCE); - scope.done(); - }); - - it('_checkIsGCE should retry the check for isGCE on transient http errors', async () => { - assert.notStrictEqual(true, auth.isGCE); - // the first request will fail, the second one will succeed - const scopes = [nock500GCE(), nockIsGCE()]; - await auth._checkIsGCE(); - assert.strictEqual(true, auth.isGCE); - scopes.forEach(s => s.done()); - }); - - it('_checkIsGCE should return false on unexpected errors', async () => { - assert.notStrictEqual(true, auth.isGCE); - const scope = nock500GCE(); - assert.strictEqual(await auth._checkIsGCE(), false); - assert.strictEqual(auth.isGCE, false); - scope.done(); - }); + it("_checkIsGCE should be equalivalent should use GCP metadata's checks", async () => { + nockNotGCE(); - it('_checkIsGCE should not retry the check for isGCE if it fails with an ENOTFOUND', async () => { - assert.notStrictEqual(true, auth.isGCE); - const scope = nockNotGCE(); - await auth._checkIsGCE(); - assert.strictEqual(false as boolean, auth.isGCE); - scope.done(); - }); - - it('_checkIsGCE does not execute the second time when running on GCE', async () => { - // This test relies on the nock mock only getting called once. - assert.notStrictEqual(true, auth.isGCE); - const scope = nockIsGCE(); - await auth._checkIsGCE(); - assert.strictEqual(true, auth.isGCE); - await auth._checkIsGCE(); - assert.strictEqual(true, auth.isGCE); - scope.done(); - }); + const expected = await (gcpMetadata.getGCPResidency() || + gcpMetadata.isAvailable()); - it('_checkIsGCE does not execute the second time when not running on GCE', async () => { - assert.notStrictEqual(true, auth.isGCE); - const scope = nockNotGCE(); - await auth._checkIsGCE(); - assert.strictEqual(false as boolean, auth.isGCE); + assert.strict.notEqual(auth.isGCE, true); await auth._checkIsGCE(); - assert.strictEqual(false as boolean, auth.isGCE); - scope.done(); + assert.strictEqual(auth.isGCE, expected); }); it('getCredentials should get metadata from the server when running on GCE', async () => {