From 97457c120e696fc7027645b2c8c0cbfe1b51af7f Mon Sep 17 00:00:00 2001 From: LiuJoyceC Date: Fri, 24 Jun 2016 16:00:22 -0700 Subject: [PATCH 1/4] Adds a new credential provider for ECS and puts it in the default credential chain provider --- lib/aws.js | 8 +- lib/credentials/credential_provider_chain.js | 7 +- lib/credentials/ecs_credentials.js | 130 +++++++++++++++++++ test/credentials.spec.coffee | 90 +++++++++++++ 4 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 lib/credentials/ecs_credentials.js diff --git a/lib/aws.js b/lib/aws.js index 288ac58972..1f6a8fef36 100644 --- a/lib/aws.js +++ b/lib/aws.js @@ -15,6 +15,7 @@ require('./services'); // Load custom credential providers require('./credentials/ec2_metadata_credentials'); +require('./credentials/ecs_credentials'); require('./credentials/environment_credentials'); require('./credentials/file_system_credentials'); require('./credentials/shared_ini_file_credentials'); @@ -24,7 +25,12 @@ AWS.CredentialProviderChain.defaultProviders = [ function () { return new AWS.EnvironmentCredentials('AWS'); }, function () { return new AWS.EnvironmentCredentials('AMAZON'); }, function () { return new AWS.SharedIniFileCredentials(); }, - function () { return new AWS.EC2MetadataCredentials(); } + function () { + if (AWS.ECSCredentials.prototype.getECSRelativeUri() !== undefined) { + return new AWS.ECSCredentials(); + } + return new AWS.EC2MetadataCredentials(); + } ]; // Update configuration keys diff --git a/lib/credentials/credential_provider_chain.js b/lib/credentials/credential_provider_chain.js index 604d11b290..1411f14be9 100644 --- a/lib/credentials/credential_provider_chain.js +++ b/lib/credentials/credential_provider_chain.js @@ -123,7 +123,12 @@ AWS.CredentialProviderChain = AWS.util.inherit(AWS.Credentials, { * function () { return new AWS.EnvironmentCredentials('AWS'); }, * function () { return new AWS.EnvironmentCredentials('AMAZON'); }, * function () { return new AWS.SharedIniFileCredentials(); }, - * function () { return new AWS.EC2MetadataCredentials(); } + * function () { + * if (AWS.ECSCredentials.prototype.getECSRelativeUri() !== undefined) { + * return new AWS.ECSCredentials(); + * } + * return new AWS.EC2MetadataCredentials(); + * } * ] * ``` */ diff --git a/lib/credentials/ecs_credentials.js b/lib/credentials/ecs_credentials.js new file mode 100644 index 0000000000..a286e7cabb --- /dev/null +++ b/lib/credentials/ecs_credentials.js @@ -0,0 +1,130 @@ +var AWS = require('../core'); +require('../metadata_service'); + +/** + * Represents credentials received from relative URI specified in the ECS container. + * + * This class will request refreshable credentials from the relative URI + * specified by the AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variable + * in the container. If valid credentials are returned in the response, these + * will be used with zero configuration. + * + * This credentials class will timeout after 1 second of inactivity by default. + * If your requests to the relative URI are timing out, you can increase + * the value by configuring them directly: + * + * ```javascript + * AWS.config.credentials = new AWS.ECSCredentials({ + * httpOptions: { timeout: 5000 } // 5 second timeout + * }); + * ``` + * + * @!macro nobrowser + */ +AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { + constructor: function ECSCredentials(options) { + AWS.Credentials.call(this); + options = options ? AWS.util.copy(options) : {}; + if (!options.httpOptions) options.httpOptions = {}; + options.httpOptions = AWS.util.merge( + this.httpOptions, options.httpOptions); + AWS.util.update(this, options); + }, + + /** + * @api private + */ + httpOptions: { timeout: 1000 }, + + /** + * @api private + */ + host: '169.254.170.2', + + /** + * @api private + */ + environmentVar: 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI', + + /** + * @api private + */ + getECSRelativeUri: function getECSRelativeUri() { + if (process) return process.env[this.environmentVar]; + }, + + /** + * @api private + */ + credsFormatIsValid: function credsFormatIsValid(credData) { + return (!!credData.AccessKeyId && !!credData.SecretAccessKey && + !!credData.Token && !!credData.Expiration); + }, + + /** + * @api private + */ + request: function request(path, callback) { + path = path || '/'; + + var data = ''; + var http = AWS.HttpClient.getInstance(); + var httpRequest = new AWS.HttpRequest('http://' + this.host + path); + httpRequest.method = 'GET'; + httpRequest.headers.Accept = 'application/json'; + var httpOptions = this.httpOptions; + + process.nextTick(function() { + http.handleRequest(httpRequest, httpOptions, function(httpResponse) { + httpResponse.on('data', function(chunk) { data += chunk.toString(); }); + httpResponse.on('end', function() { callback(null, data); }); + }, callback); + }); + }, + + /** + * Loads the credentials from the relative URI specified by container + * + * @callback callback function(err) + * Called when the request to the relative URI responds (or fails). When + * this callback is called with no error, it means that the credentials + * information has been loaded into the object (as the `accessKeyId`, + * `secretAccessKey`, `sessionToken`, and `expireTime` properties). + * @param err [Error] if an error occurred, this value will be filled + * @see get + */ + refresh: function refresh(callback) { + var self = this; + if (!callback) callback = function(err) { if (err) throw err; }; + + if (process === undefined) { + callback(new Error('No process info available')); + return; + } + var relativeUri = this.getECSRelativeUri(); + if (relativeUri === undefined) { + callback(new Error('Variable ' + this.environmentVar + ' not set.')); + return; + } + + this.request(relativeUri, function(err, data) { + if (!err) { + try { + var creds = JSON.parse(data); + if (self.credsFormatIsValid(creds)) { + self.expired = false; + self.accessKeyId = creds.AccessKeyId; + self.secretAccessKey = creds.SecretAccessKey; + self.sessionToken = creds.Token; + self.expireTime = new Date(creds.Expiration); + } else { + throw new Error('Data is not in valid format'); + } + } catch (dataError) { + err = dataError; + } + } + callback(err); + }); + } +}); diff --git a/test/credentials.spec.coffee b/test/credentials.spec.coffee index aa3dbba308..01cbc09844 100644 --- a/test/credentials.spec.coffee +++ b/test/credentials.spec.coffee @@ -425,6 +425,96 @@ if AWS.util.isNode() creds.refresh -> expect(spy.calls.length).to.equal(4) + describe 'AWS.ECSCredentials', -> + creds = null + + beforeEach -> + creds = new AWS.ECSCredentials(host: 'host') + process.env = {} + + afterEach -> + process.env = {} + + mockEndpoint = (expireTime) -> + helpers.spyOn(creds, 'request').andCallFake (path, cb) -> + cb null, + JSON.stringify({ + AccessKeyId: 'KEY' + SecretAccessKey: 'SECRET' + Token: 'TOKEN' + Expiration: expireTime.toISOString() + }) + + describe 'constructor', -> + it 'allows passing of options', -> + expect(creds.host).to.equal('host') + + it 'does not modify options object', -> + opts = {} + creds = new AWS.ECSCredentials(opts) + expect(opts).to.eql({}) + + it 'allows setting timeout', -> + opts = httpOptions: timeout: 5000 + creds = new AWS.ECSCredentials(opts) + expect(creds.httpOptions.timeout).to.equal(5000) + + describe 'getECSRelativeUri', -> + it 'returns undefined when process is not available', -> + process_copy = process + process = undefined + expect(creds.getECSRelativeUri()).to.equal(undefined) + process = process_copy + + it 'returns undefined when relative URI environment variable not set', -> + expect(creds.getECSRelativeUri()).to.equal(undefined) + + it 'returns relative URI when environment variable is set', -> + process.env[creds.environmentVar] = '/path' + expect(creds.getECSRelativeUri()).to.equal('/path') + + describe 'credsFormatIsValid', -> + it 'returns false when data is missing required property', -> + responseData = {AccessKeyId: 'KEY', SecretAccessKey: 'SECRET', Token: 'TOKEN'} + expect(creds.credsFormatIsValid(responseData)).to.be.false + + it 'returns true when data has all required properties', -> + responseData = { + AccessKeyId: 'KEY', + SecretAccessKey: 'SECRET', + Token: 'TOKEN', + Expiration: (new Date(0)).toISOString() + } + expect(creds.credsFormatIsValid(responseData)).to.be.true + + describe 'needsRefresh', -> + it 'can be expired based on expire time from URI endpoint', -> + process.env[creds.environmentVar] = '/path' + spy = mockEndpoint(new Date(0)) + creds.refresh(->) + expect(spy.calls.length).to.equal(1) + expect(creds.needsRefresh()).to.equal(true) + + describe 'refresh', -> + it 'loads credentials from specified relative URI', -> + callbackErr = null + process.env[creds.environmentVar] = '/path' + spy = mockEndpoint(new Date(AWS.util.date.getDate().getTime() + 100000)) + creds.refresh((err) -> callbackErr = err) + expect(spy.calls.length).to.equal(1) + expect(callbackErr).to.be.null + expect(creds.accessKeyId).to.equal('KEY') + expect(creds.secretAccessKey).to.equal('SECRET') + expect(creds.sessionToken).to.equal('TOKEN') + expect(creds.needsRefresh()).to.equal(false) + + it 'passes an error to the callback when environment variable not set', -> + callbackErr = null + spy = mockEndpoint(new Date(AWS.util.date.getDate().getTime() + 100000)) + creds.refresh((err) -> callbackErr = err) + expect(spy.calls.length).to.equal(0) + expect(callbackErr).to.not.be.null + describe 'AWS.TemporaryCredentials', -> creds = null From 383c0308343b32c47373942355d936d74af3f675 Mon Sep 17 00:00:00 2001 From: LiuJoyceC Date: Wed, 29 Jun 2016 14:19:17 -0700 Subject: [PATCH 2/4] Adds error codes to errors returned from credential providers. --- lib/aws.js | 3 ++ lib/credentials/credential_provider_chain.js | 6 +-- lib/credentials/ecs_credentials.js | 22 ++++++-- lib/credentials/environment_credentials.js | 12 +++-- lib/credentials/file_system_credentials.js | 5 +- .../shared_ini_file_credentials.js | 51 +++++++++++++------ test/credentials.spec.coffee | 6 +-- 7 files changed, 74 insertions(+), 31 deletions(-) diff --git a/lib/aws.js b/lib/aws.js index 1f6a8fef36..0ed88f0b7e 100644 --- a/lib/aws.js +++ b/lib/aws.js @@ -21,6 +21,9 @@ require('./credentials/file_system_credentials'); require('./credentials/shared_ini_file_credentials'); // Setup default chain providers +// If this changes, please update documentation for +// AWS.CredentialProviderChain.defaultProviders in +// credentials/credential_provider_chain.js AWS.CredentialProviderChain.defaultProviders = [ function () { return new AWS.EnvironmentCredentials('AWS'); }, function () { return new AWS.EnvironmentCredentials('AMAZON'); }, diff --git a/lib/credentials/credential_provider_chain.js b/lib/credentials/credential_provider_chain.js index 1411f14be9..79bed3d060 100644 --- a/lib/credentials/credential_provider_chain.js +++ b/lib/credentials/credential_provider_chain.js @@ -124,10 +124,10 @@ AWS.CredentialProviderChain = AWS.util.inherit(AWS.Credentials, { * function () { return new AWS.EnvironmentCredentials('AMAZON'); }, * function () { return new AWS.SharedIniFileCredentials(); }, * function () { - * if (AWS.ECSCredentials.prototype.getECSRelativeUri() !== undefined) { + * // if AWS_CONTAINER_CREDENTIALS_RELATIVE_URI is set * return new AWS.ECSCredentials(); - * } - * return new AWS.EC2MetadataCredentials(); + * // else + * return new AWS.EC2MetadataCredentials(); * } * ] * ``` diff --git a/lib/credentials/ecs_credentials.js b/lib/credentials/ecs_credentials.js index a286e7cabb..38df3f7557 100644 --- a/lib/credentials/ecs_credentials.js +++ b/lib/credentials/ecs_credentials.js @@ -1,5 +1,4 @@ var AWS = require('../core'); -require('../metadata_service'); /** * Represents credentials received from relative URI specified in the ECS container. @@ -42,6 +41,10 @@ AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { host: '169.254.170.2', /** + * Sets the name of the ECS environment variable to check for relative URI + * If changed, please change the name in the documentation for defaultProvider + * in credential_provider_chain.js and in all tests in test/credentials.spec.coffee + * * @api private */ environmentVar: 'AWS_CONTAINER_CREDENTIALS_RELATIVE_URI', @@ -50,7 +53,7 @@ AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { * @api private */ getECSRelativeUri: function getECSRelativeUri() { - if (process) return process.env[this.environmentVar]; + if (process && process.env) return process.env[this.environmentVar]; }, /** @@ -98,12 +101,18 @@ AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { if (!callback) callback = function(err) { if (err) throw err; }; if (process === undefined) { - callback(new Error('No process info available')); + callback(AWS.util.error( + new Error('No process info available'), + { code: 'ECSCredentialsProviderFailure' } + )); return; } var relativeUri = this.getECSRelativeUri(); if (relativeUri === undefined) { - callback(new Error('Variable ' + this.environmentVar + ' not set.')); + callback(AWS.util.error( + new Error('Variable ' + this.environmentVar + ' not set.'), + { code: 'ECSCredentialsProviderFailure' } + )); return; } @@ -118,7 +127,10 @@ AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { self.sessionToken = creds.Token; self.expireTime = new Date(creds.Expiration); } else { - throw new Error('Data is not in valid format'); + throw AWS.util.error( + new Error('Response data is not in valid format'), + { code: 'ECSCredentialsProviderFailure' } + ); } } catch (dataError) { err = dataError; diff --git a/lib/credentials/environment_credentials.js b/lib/credentials/environment_credentials.js index dc4d9ea749..b406518d2c 100644 --- a/lib/credentials/environment_credentials.js +++ b/lib/credentials/environment_credentials.js @@ -59,8 +59,11 @@ AWS.EnvironmentCredentials = AWS.util.inherit(AWS.Credentials, { refresh: function refresh(callback) { if (!callback) callback = function(err) { if (err) throw err; }; - if (process === undefined) { - callback(new Error('No process info available')); + if (!process || !process.env) { + callback(AWS.util.error( + new Error('No process info or environment variables available'), + { code: 'EnvironmentCredentialsProviderFailure' } + )); return; } @@ -72,7 +75,10 @@ AWS.EnvironmentCredentials = AWS.util.inherit(AWS.Credentials, { if (this.envPrefix) prefix = this.envPrefix + '_'; values[i] = process.env[prefix + keys[i]]; if (!values[i] && keys[i] !== 'SESSION_TOKEN') { - callback(new Error('Variable ' + prefix + keys[i] + ' not set.')); + callback(AWS.util.error( + new Error('Variable ' + prefix + keys[i] + ' not set.'), + { code: 'EnvironmentCredentialsProviderFailure' } + )); return; } } diff --git a/lib/credentials/file_system_credentials.js b/lib/credentials/file_system_credentials.js index 8d5d0de95d..f6d6fc138e 100644 --- a/lib/credentials/file_system_credentials.js +++ b/lib/credentials/file_system_credentials.js @@ -53,7 +53,10 @@ AWS.FileSystemCredentials = AWS.util.inherit(AWS.Credentials, { var creds = JSON.parse(AWS.util.readFileSync(this.filename)); AWS.Credentials.call(this, creds); if (!this.accessKeyId || !this.secretAccessKey) { - throw new Error('Credentials not set in ' + this.filename); + throw AWS.util.error( + new Error('Credentials not set in ' + this.filename), + { code: 'FileSystemCredentialsProviderFailure' } + ); } this.expired = false; callback(); diff --git a/lib/credentials/shared_ini_file_credentials.js b/lib/credentials/shared_ini_file_credentials.js index 45dae1bd6a..9393990e33 100644 --- a/lib/credentials/shared_ini_file_credentials.js +++ b/lib/credentials/shared_ini_file_credentials.js @@ -74,8 +74,10 @@ AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { var profile = creds[this.profile]; if (typeof profile !== 'object') { - throw new Error('Profile ' + this.profile + ' not found in ' + - this.filename); + throw AWS.util.error( + new Error('Profile ' + this.profile + ' not found in ' + this.filename), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } if (profile['role_arn']) { @@ -88,8 +90,11 @@ AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { this.sessionToken = profile['aws_session_token']; if (!this.accessKeyId || !this.secretAccessKey) { - throw new Error('Credentials not set in ' + this.filename + - ' using profile ' + this.profile); + throw AWS.util.error( + new Error('Credentials not set in ' + this.filename + + ' using profile ' + this.profile), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } this.expired = false; callback(); @@ -103,9 +108,12 @@ AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { */ loadRoleProfile: function loadRoleProfile(creds, roleProfile, callback) { if (this.disableAssumeRole) { - throw new Error('Role assumption profiles are disabled. ' + - 'Failed to load profile ' + this.profile + ' from ' + - this.filename); + throw AWS.util.error( + new Error('Role assumption profiles are disabled. ' + + 'Failed to load profile ' + this.profile + ' from ' + + this.filename), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } var self = this; @@ -115,16 +123,22 @@ AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { var sourceProfileName = roleProfile['source_profile']; if (!sourceProfileName) { - throw new Error('source_profile is not set in ' + this.filename + - ' using profile ' + this.profile); + throw AWS.util.error( + new Error('source_profile is not set in ' + this.filename + + ' using profile ' + this.profile), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } var sourceProfile = creds[sourceProfileName]; if (typeof sourceProfile !== 'object') { - throw new Error('source_profile ' + sourceProfileName + ' set in ' + - this.filename + ' using profile ' + this.profile + - ' does not exist') + throw AWS.util.error( + new Error('source_profile ' + sourceProfileName + ' set in ' + + this.filename + ' using profile ' + this.profile + + ' does not exist'), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } var sourceCredentials = { @@ -134,9 +148,12 @@ AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { }; if (!sourceCredentials.accessKeyId || !sourceCredentials.secretAccessKey) { - throw new Error('Credentials not set in source_profile ' + - sourceProfileName + ' set in ' + this.filename + - ' using profile ' + this.profile); + throw AWS.util.error( + new Error('Credentials not set in source_profile ' + + sourceProfileName + ' set in ' + this.filename + + ' using profile ' + this.profile), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } var sts = new AWS.STS({ @@ -176,7 +193,9 @@ AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { (env.HOMEPATH ? ((env.HOMEDRIVE || 'C:/') + env.HOMEPATH) : null); if (!home) { throw AWS.util.error( - new Error('Cannot load credentials, HOME path not set')); + new Error('Cannot load credentials, HOME path not set'), + { code: 'SharedIniFileCredentialsProviderFailure' } + ); } this.filename = path.join(home, '.aws', 'credentials'); diff --git a/test/credentials.spec.coffee b/test/credentials.spec.coffee index 01cbc09844..e079aab3ba 100644 --- a/test/credentials.spec.coffee +++ b/test/credentials.spec.coffee @@ -470,7 +470,7 @@ if AWS.util.isNode() expect(creds.getECSRelativeUri()).to.equal(undefined) it 'returns relative URI when environment variable is set', -> - process.env[creds.environmentVar] = '/path' + process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/path' expect(creds.getECSRelativeUri()).to.equal('/path') describe 'credsFormatIsValid', -> @@ -489,7 +489,7 @@ if AWS.util.isNode() describe 'needsRefresh', -> it 'can be expired based on expire time from URI endpoint', -> - process.env[creds.environmentVar] = '/path' + process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/path' spy = mockEndpoint(new Date(0)) creds.refresh(->) expect(spy.calls.length).to.equal(1) @@ -498,7 +498,7 @@ if AWS.util.isNode() describe 'refresh', -> it 'loads credentials from specified relative URI', -> callbackErr = null - process.env[creds.environmentVar] = '/path' + process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/path' spy = mockEndpoint(new Date(AWS.util.date.getDate().getTime() + 100000)) creds.refresh((err) -> callbackErr = err) expect(spy.calls.length).to.equal(1) From b2593f2e22432eb6ba3e9aad7df70c6f34abb22d Mon Sep 17 00:00:00 2001 From: LiuJoyceC Date: Tue, 12 Jul 2016 16:11:31 -0700 Subject: [PATCH 3/4] Adds reference to getECSRelativeUri function on the ECSCredentials constructor --- lib/aws.js | 2 +- lib/credentials/ecs_credentials.js | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/aws.js b/lib/aws.js index 0ed88f0b7e..e8479f4933 100644 --- a/lib/aws.js +++ b/lib/aws.js @@ -29,7 +29,7 @@ AWS.CredentialProviderChain.defaultProviders = [ function () { return new AWS.EnvironmentCredentials('AMAZON'); }, function () { return new AWS.SharedIniFileCredentials(); }, function () { - if (AWS.ECSCredentials.prototype.getECSRelativeUri() !== undefined) { + if (AWS.ECSCredentials.getECSRelativeUri() !== undefined) { return new AWS.ECSCredentials(); } return new AWS.EC2MetadataCredentials(); diff --git a/lib/credentials/ecs_credentials.js b/lib/credentials/ecs_credentials.js index 38df3f7557..fd5ebe3486 100644 --- a/lib/credentials/ecs_credentials.js +++ b/lib/credentials/ecs_credentials.js @@ -140,3 +140,8 @@ AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { }); } }); + +/** + * @api private + */ +AWS.ECSCredentials.getECSRelativeUri = AWS.ECSCredentials.prototype.getECSRelativeUri; From d15a412076ade4cbbd71c506eb39bf802e1c424d Mon Sep 17 00:00:00 2001 From: LiuJoyceC Date: Wed, 13 Jul 2016 12:25:50 -0700 Subject: [PATCH 4/4] Revert back to calling getECSRelativeUri on ECSCredentials.prototype. --- lib/aws.js | 2 +- lib/credentials/ecs_credentials.js | 5 ----- test/credentials.spec.coffee | 4 ++++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/aws.js b/lib/aws.js index e8479f4933..0ed88f0b7e 100644 --- a/lib/aws.js +++ b/lib/aws.js @@ -29,7 +29,7 @@ AWS.CredentialProviderChain.defaultProviders = [ function () { return new AWS.EnvironmentCredentials('AMAZON'); }, function () { return new AWS.SharedIniFileCredentials(); }, function () { - if (AWS.ECSCredentials.getECSRelativeUri() !== undefined) { + if (AWS.ECSCredentials.prototype.getECSRelativeUri() !== undefined) { return new AWS.ECSCredentials(); } return new AWS.EC2MetadataCredentials(); diff --git a/lib/credentials/ecs_credentials.js b/lib/credentials/ecs_credentials.js index fd5ebe3486..38df3f7557 100644 --- a/lib/credentials/ecs_credentials.js +++ b/lib/credentials/ecs_credentials.js @@ -140,8 +140,3 @@ AWS.ECSCredentials = AWS.util.inherit(AWS.Credentials, { }); } }); - -/** - * @api private - */ -AWS.ECSCredentials.getECSRelativeUri = AWS.ECSCredentials.prototype.getECSRelativeUri; diff --git a/test/credentials.spec.coffee b/test/credentials.spec.coffee index e079aab3ba..8356c39239 100644 --- a/test/credentials.spec.coffee +++ b/test/credentials.spec.coffee @@ -473,6 +473,10 @@ if AWS.util.isNode() process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/path' expect(creds.getECSRelativeUri()).to.equal('/path') + it 'returns relative URI from prototype when environment variable is set', -> + process.env['AWS_CONTAINER_CREDENTIALS_RELATIVE_URI'] = '/path' + expect(AWS.ECSCredentials.prototype.getECSRelativeUri()).to.equal('/path') + describe 'credsFormatIsValid', -> it 'returns false when data is missing required property', -> responseData = {AccessKeyId: 'KEY', SecretAccessKey: 'SECRET', Token: 'TOKEN'}