Skip to content

Commit 5bf55fe

Browse files
committed
add support for passing an AWS.Credentials object via options.amazon.credentials
1 parent 559fcba commit 5bf55fe

File tree

3 files changed

+84
-4
lines changed

3 files changed

+84
-4
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ gulp.task('deploy', function() {
3838

3939
The code above would work as follows
4040
* Take the files sepcified by `gulp.src` and zip them on a file named `{ version }-{ timestamp }.zip` (i.e: `1.0.0-2016.04.08_13.26.32.zip`)
41-
* If amazon credentials (`accessKeyId`, `secretAccessKey`) are provided in the `amazon` object, set them on the `AWS.config.credentials`. If not provided, the default values from AWS CLI configuration will be used.
41+
* AWS credentials may be provided either in Form of a `accessKeyId` and `secretAccessKey` or a [`credentials` object](http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Credentials.html). If no credentials are provided, the default values from AWS CLI configuration will be used.
4242
* Try to upload the zipped file to the bucket specified by `amazon.bucket`. If it fails because the bucket doesn't exist, try to create the bucket and then try to upload the zipped file again
4343
* Uploads the ziped files to the bucket on the path `{{ name }}/{{ filename }}` (i.e: `my-application/1.0.0-2016.04.08_13.26.32.zip`)
4444
* Creates a new version on the Application specified by `applicationName` with VersionLabel `{ version }-{ timestamp }` (i.e: `1.0.0-2016.04.08_13.26.32`)

src/plugin.js

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { readFileSync } from 'fs'
1+
import { readFileSync, existsSync } from 'fs'
22
import { join } from 'path'
33
import { omit, isEqual } from 'lodash'
44
import { log as gulpLog, colors, PluginError } from 'gulp-util'
@@ -9,6 +9,37 @@ import AWS from 'aws-sdk'
99
import pad from 'left-pad'
1010
import { S3File, Bean } from './aws'
1111

12+
const credentialProviders = [
13+
{
14+
Ctor: AWS.SAMLCredentials,
15+
fields: [
16+
[ 'RoleArn', 'PrincipalArn', 'SAMLAssertion' ]
17+
]
18+
},
19+
{
20+
Ctor: AWS.CognitoIdentityCredentials,
21+
fields: [
22+
[ 'IdentityPoolId' ],
23+
[ 'IdentityId' ]
24+
]
25+
},
26+
{
27+
// we can only detect these if a custom profile is specified
28+
// but that is fine because shared ini file credentials using the default profile
29+
// are used by the AWS SDK when no credentials are specified
30+
Ctor: AWS.SharedIniFileCredentials,
31+
fields: [
32+
[ 'profile' ]
33+
]
34+
},
35+
{
36+
Ctor: AWS.TemporaryCredentials,
37+
fields: [
38+
[ 'SerialNumber', 'TokenCode' ],
39+
[ 'RoleArn' ]
40+
]
41+
}
42+
]
1243
const IS_TEST = process.env['NODE_ENV'] === 'test'
1344
const log = IS_TEST ? () => {} : gulpLog
1445

@@ -191,8 +222,45 @@ export function buildOptions(opts) {
191222
if (!options.amazon)
192223
throw new PluginError(PLUGIN_NAME, 'No amazon config provided')
193224

194-
// if keys are provided, create new credentials, otherwise defaults will be used
195-
if (options.amazon.accessKeyId && options.amazon.secretAccessKey) {
225+
if (options.amazon.credentials) {
226+
const creds = options.amazon.credentials
227+
const credsType = typeof(creds)
228+
229+
if (credsType === 'string') {
230+
// if the credentials are of type string, assume the user is specifying
231+
// an environment variable name prefix
232+
AWS.config.credentials = existsSync(creds) ? new AWS.EnvironmentCredentials(creds)
233+
: new AWS.FileSystemCredentials(creds)
234+
} else if (credsType !== 'object') {
235+
// otherwise the credentials must be an object
236+
throw new PluginError(PLUGIN_NAME, `Amamzon credentials must be an object, got a '${typeof(creds)}'.`)
237+
} else if (creds.constructor.name === 'Credentials' ||
238+
typeof(creds.constructor.__super__) === 'function' &&
239+
creds.constructor.__super__.name === 'Credentials') {
240+
// support pre-build objects of or inheriting the AWS.Credentials class
241+
AWS.config.credentials = creds
242+
} else if (creds.accessKeyId && creds.secretAccessKey) {
243+
// support simple access key credentials
244+
AWS.config.credentials = new AWS.Credentials(creds.accessKeyId, creds.secretAccessKey, creds.sessionToken)
245+
} else {
246+
// otherwise try to find a matching provider for the supplied credentials object
247+
// if that fails, create temporary credentials (which do not have any mandatory parameter) as a last resort
248+
const provider = credentialProviders.find(prov =>
249+
prov.fields.find(fields =>
250+
fields.every(field => creds[field] !== undefined)
251+
)
252+
)
253+
if (provider === undefined) {
254+
AWS.config.credentials = new AWS.TemporaryCredentials()
255+
} else try {
256+
AWS.config.credentials = new provider.Ctor(creds)
257+
} catch(err) {
258+
throw new PluginError(PLUGIN_NAME, `An error occured while trying to construct AWS.${provider.Ctor.name} from supplied credentials object: ${err}`)
259+
}
260+
}
261+
} else if (options.amazon.accessKeyId && options.amazon.secretAccessKey) {
262+
// legacy support for the access key id and secret access key
263+
// passed in directly via the options.amazon object
196264
AWS.config.credentials = new AWS.Credentials({
197265
accessKeyId: opts.amazon.accessKeyId,
198266
secretAccessKey: opts.amazon.secretAccessKey

test/test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,18 @@ describe('Gulp plugin', () => {
578578
AWS.Credentials.called.should.be.false()
579579
should(AWS.config.credentials).be.null()
580580
})
581+
582+
it('updates AWS.config.credentials with a Credentials object', () => {
583+
spy(AWS, 'Credentials')
584+
const credentials = new AWS.Credentials()
585+
buildOptions({
586+
amazon: {
587+
credentials: credentials
588+
}
589+
})
590+
AWS.Credentials.calledOnce.should.be.true()
591+
AWS.config.credentials.should.be.equal(credentials)
592+
})
581593
})
582594

583595
describe('gulpEbDeploy', () => {

0 commit comments

Comments
 (0)