diff --git a/src/index.ts b/src/index.ts index 27f9f37ce..3d3162cda 100644 --- a/src/index.ts +++ b/src/index.ts @@ -505,11 +505,13 @@ class Datastore extends DatastoreRequest { }, options ); - const isUsingEmulator = + const isUsingLocalhost = this.baseUrl_ && (this.baseUrl_.includes('localhost') || this.baseUrl_.includes('127.0.0.1') || this.baseUrl_.includes('::1')); + const isEmulatorVariableSet = process.env.DATASTORE_EMULATOR_HOST; + const isUsingEmulator = isUsingLocalhost || isEmulatorVariableSet; if (this.customEndpoint_ && isUsingEmulator) { this.options.sslCreds ??= grpc.credentials.createInsecure(); } diff --git a/test/index.ts b/test/index.ts index f0bfae0da..6b9d2b9b6 100644 --- a/test/index.ts +++ b/test/index.ts @@ -316,6 +316,139 @@ async.each( assert.strictEqual(datastore.options.sslCreds, fakeInsecureCreds); }); + describe('checking ssl credentials are set correctly with custom endpoints', () => { + function setHost(host: string) { + process.env.DATASTORE_EMULATOR_HOST = host; + } + + const sslCreds = gax.grpc.ChannelCredentials.createSsl(); + const fakeInsecureCreds = { + insecureCredProperty: 'insecureCredPropertyValue', + }; + + beforeEach(() => { + createInsecureOverride = () => { + return fakeInsecureCreds; + }; + }); + + describe('without DATASTORE_EMULATOR_HOST environment variable set', () => { + beforeEach(() => { + delete process.env.DATASTORE_EMULATOR_HOST; + }); + + describe('using a localhost endpoint', () => { + const apiEndpoint = 'http://localhost:8080'; + it('should use ssl credentials provided', () => { + // SSL credentials provided in the constructor should always be used. + const options = { + apiEndpoint, + sslCreds, + }; + const datastore = new Datastore(options); + assert.strictEqual(datastore.options.sslCreds, sslCreds); + }); + it('should use insecure ssl credentials when ssl credentials are not provided', () => { + // When using a localhost endpoint it is assumed that the emulator is being used. + // Therefore, sslCreds should be set to insecure credentials to skip authentication. + const datastore = new Datastore({ + apiEndpoint, + }); + assert.strictEqual( + datastore.options.sslCreds, + fakeInsecureCreds + ); + }); + }); + describe('using a remote endpoint', () => { + const apiEndpoint = 'http://remote:8080'; + it('should use ssl credentials provided', () => { + // SSL credentials provided in the constructor should always be used. + const options = { + apiEndpoint, + sslCreds, + }; + const datastore = new Datastore(options); + assert.strictEqual(datastore.options.sslCreds, sslCreds); + }); + it('should not set ssl credentials when ssl credentials are not provided', () => { + // When using a remote endpoint without DATASTORE_EMULATOR_HOST set, + // it is assumed that the emulator is not being used. + // This test captures the case where users use a regional endpoint. + const datastore = new Datastore({ + apiEndpoint, + }); + assert.strictEqual(datastore.options.sslCreds, undefined); + }); + }); + }); + describe('with DATASTORE_EMULATOR_HOST environment variable set', () => { + beforeEach(() => { + delete process.env.DATASTORE_EMULATOR_HOST; + }); + + describe('with DATASTORE_EMULATOR_HOST set to localhost', () => { + const apiEndpoint = 'http://localhost:8080'; + beforeEach(() => { + setHost(apiEndpoint); + }); + + it('should use ssl credentials provided', () => { + // SSL credentials provided in the constructor should always be used. + const datastore = new Datastore({ + apiEndpoint, + sslCreds, + }); + assert.strictEqual(datastore.options.sslCreds, sslCreds); + }); + + it('should use insecure ssl credentials when ssl credentials are not provided', () => { + // When DATASTORE_EMULATOR_HOST is set it is assumed that the emulator is being used. + // Therefore, sslCreds should be set to insecure credentials to skip authentication. + const datastore = new Datastore({ + apiEndpoint, + }); + assert.strictEqual( + datastore.options.sslCreds, + fakeInsecureCreds + ); + }); + }); + + describe('with DATASTORE_EMULATOR_HOST set to remote host', () => { + const apiEndpoint = 'http://remote:8080'; + beforeEach(() => { + setHost(apiEndpoint); + }); + + it('should use ssl credentials provided', () => { + // SSL credentials provided in the constructor should always be used. + const datastore = new Datastore({ + apiEndpoint, + sslCreds, + }); + assert.strictEqual(datastore.options.sslCreds, sslCreds); + }); + + it('should use insecure ssl credentials when ssl credentials are not provided', () => { + // When DATASTORE_EMULATOR_HOST is set it is assumed that the emulator is being used. + // Therefore, sslCreds should be set to insecure credentials to skip authentication. + const datastore = new Datastore({ + apiEndpoint, + }); + assert.strictEqual( + datastore.options.sslCreds, + fakeInsecureCreds + ); + }); + }); + + after(() => { + delete process.env.DATASTORE_EMULATOR_HOST; + }); + }); + }); + it('should cache a local GoogleAuth instance', () => { const fakeGoogleAuthInstance = {};