shared_ini_file_credentials.js (6667B)
1 var AWS = require('../core'); 2 var path = require('path'); 3 var STS = require('../../clients/sts'); 4 5 /** 6 * Represents credentials loaded from shared credentials file 7 * (defaulting to ~/.aws/credentials). 8 * 9 * ## Using the shared credentials file 10 * 11 * This provider is checked by default in the Node.js environment. To use the 12 * credentials file provider, simply add your access and secret keys to the 13 * ~/.aws/credentials file in the following format: 14 * 15 * [default] 16 * aws_access_key_id = AKID... 17 * aws_secret_access_key = YOUR_SECRET_KEY 18 * 19 * ## Using custom profiles 20 * 21 * The SDK supports loading credentials for separate profiles. This can be done 22 * in two ways: 23 * 24 * 1. Set the `AWS_PROFILE` environment variable in your process prior to 25 * loading the SDK. 26 * 2. Directly load the AWS.SharedIniFileCredentials provider: 27 * 28 * ```javascript 29 * var creds = new AWS.SharedIniFileCredentials({profile: 'myprofile'}); 30 * AWS.config.credentials = creds; 31 * ``` 32 * 33 * @!macro nobrowser 34 */ 35 AWS.SharedIniFileCredentials = AWS.util.inherit(AWS.Credentials, { 36 /** 37 * Creates a new SharedIniFileCredentials object. 38 * 39 * @param options [map] a set of options 40 * @option options profile [String] (AWS_PROFILE env var or 'default') 41 * the name of the profile to load. 42 * @option options filename [String] ('~/.aws/credentials') the filename 43 * to use when loading credentials. 44 * @option options disableAssumeRole [Boolean] (false) True to disable 45 * support for profiles that assume an IAM role. If true, and an assume 46 * role profile is selected, an error is raised. 47 */ 48 constructor: function SharedIniFileCredentials(options) { 49 AWS.Credentials.call(this); 50 51 options = options || {}; 52 53 this.filename = options.filename; 54 this.profile = options.profile || process.env.AWS_PROFILE || 'default'; 55 this.disableAssumeRole = !!options.disableAssumeRole; 56 this.get(function() {}); 57 }, 58 59 /** 60 * Loads the credentials from the shared credentials file 61 * 62 * @callback callback function(err) 63 * Called after the shared INI file on disk is read and parsed. When this 64 * callback is called with no error, it means that the credentials 65 * information has been loaded into the object (as the `accessKeyId`, 66 * `secretAccessKey`, and `sessionToken` properties). 67 * @param err [Error] if an error occurred, this value will be filled 68 * @see get 69 */ 70 refresh: function refresh(callback) { 71 if (!callback) callback = function(err) { if (err) throw err; }; 72 try { 73 if (!this.filename) this.loadDefaultFilename(); 74 var creds = AWS.util.ini.parse(AWS.util.readFileSync(this.filename)); 75 var profile = creds[this.profile]; 76 77 if (typeof profile !== 'object') { 78 throw AWS.util.error( 79 new Error('Profile ' + this.profile + ' not found in ' + this.filename), 80 { code: 'SharedIniFileCredentialsProviderFailure' } 81 ); 82 } 83 84 if (profile['role_arn']) { 85 this.loadRoleProfile(creds, profile, callback); 86 return; 87 } 88 89 this.accessKeyId = profile['aws_access_key_id']; 90 this.secretAccessKey = profile['aws_secret_access_key']; 91 this.sessionToken = profile['aws_session_token']; 92 93 if (!this.accessKeyId || !this.secretAccessKey) { 94 throw AWS.util.error( 95 new Error('Credentials not set in ' + this.filename + 96 ' using profile ' + this.profile), 97 { code: 'SharedIniFileCredentialsProviderFailure' } 98 ); 99 } 100 this.expired = false; 101 callback(); 102 } catch (err) { 103 callback(err); 104 } 105 }, 106 107 /** 108 * @api private 109 */ 110 loadRoleProfile: function loadRoleProfile(creds, roleProfile, callback) { 111 if (this.disableAssumeRole) { 112 throw AWS.util.error( 113 new Error('Role assumption profiles are disabled. ' + 114 'Failed to load profile ' + this.profile + ' from ' + 115 this.filename), 116 { code: 'SharedIniFileCredentialsProviderFailure' } 117 ); 118 } 119 120 var self = this; 121 var roleArn = roleProfile['role_arn']; 122 var roleSessionName = roleProfile['role_session_name']; 123 var externalId = roleProfile['external_id']; 124 var sourceProfileName = roleProfile['source_profile']; 125 126 if (!sourceProfileName) { 127 throw AWS.util.error( 128 new Error('source_profile is not set in ' + this.filename + 129 ' using profile ' + this.profile), 130 { code: 'SharedIniFileCredentialsProviderFailure' } 131 ); 132 } 133 134 var sourceProfile = creds[sourceProfileName]; 135 136 if (typeof sourceProfile !== 'object') { 137 throw AWS.util.error( 138 new Error('source_profile ' + sourceProfileName + ' set in ' + 139 this.filename + ' using profile ' + this.profile + 140 ' does not exist'), 141 { code: 'SharedIniFileCredentialsProviderFailure' } 142 ); 143 } 144 145 var sourceCredentials = { 146 accessKeyId: sourceProfile['aws_access_key_id'], 147 secretAccessKey: sourceProfile['aws_secret_access_key'], 148 sessionToken: sourceProfile['aws_session_token'] 149 }; 150 151 if (!sourceCredentials.accessKeyId || !sourceCredentials.secretAccessKey) { 152 throw AWS.util.error( 153 new Error('Credentials not set in source_profile ' + 154 sourceProfileName + ' set in ' + this.filename + 155 ' using profile ' + this.profile), 156 { code: 'SharedIniFileCredentialsProviderFailure' } 157 ); 158 } 159 160 var sts = new STS({ 161 credentials: new AWS.Credentials(sourceCredentials) 162 }); 163 164 var roleParams = { 165 RoleArn: roleArn, 166 RoleSessionName: roleSessionName || 'aws-sdk-js-' + Date.now() 167 }; 168 169 if (externalId) { 170 roleParams.ExternalId = externalId; 171 } 172 173 sts.assumeRole(roleParams, function (err, data) { 174 if (err) { 175 callback(err); 176 return; 177 } 178 179 self.accessKeyId = data.Credentials.AccessKeyId; 180 self.secretAccessKey = data.Credentials.SecretAccessKey; 181 self.sessionToken = data.Credentials.SessionToken; 182 self.expireTime = data.Credentials.Expiration; 183 callback(); 184 }); 185 }, 186 187 /** 188 * @api private 189 */ 190 loadDefaultFilename: function loadDefaultFilename() { 191 var env = process.env; 192 var home = env.HOME || 193 env.USERPROFILE || 194 (env.HOMEPATH ? ((env.HOMEDRIVE || 'C:/') + env.HOMEPATH) : null); 195 if (!home) { 196 throw AWS.util.error( 197 new Error('Cannot load credentials, HOME path not set'), 198 { code: 'SharedIniFileCredentialsProviderFailure' } 199 ); 200 } 201 202 this.filename = path.join(home, '.aws', 'credentials'); 203 } 204 });