Skip to content

Commit 89f3308

Browse files
committed
Use ~/.aws/credentials file when no access/secret is given in cli
Signed-off-by: Jean-Laurent de Morlhon <jeanlaurent@morlhon.net>
1 parent 599a84b commit 89f3308

File tree

3 files changed

+132
-13
lines changed

3 files changed

+132
-13
lines changed

docs/drivers/aws.md

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,44 @@ parent="smn_machine_drivers"
1010

1111
# Amazon Web Services
1212

13-
Create machines on [Amazon Web Services](http://aws.amazon.com). To create machines on [Amazon Web Services](http://aws.amazon.com), you must supply two required parameters:
13+
Create machines on [Amazon Web Services](http://aws.amazon.com).
1414

15-
- Access Key ID
16-
- Secret Access Key
15+
To create machines on [Amazon Web Services](http://aws.amazon.com), you must supply two parameters: the AWS Access Key ID and the AWS Secret Access Key.
1716

18-
Obtain your IDs and Keys from AWS.
1917

20-
To create the machine instance, specify `--driver amazonec2` and the three required parameters.
18+
## Configuring credentials
19+
20+
Before using the amazonec2 driver, ensure that you've configured credentials.
21+
22+
### AWS credential file
23+
One way to configure credentials is to use the standard credential file for Amazon AWS `~/.aws/credentials` file, which might look like:
24+
25+
[default]
26+
aws_access_key_id = AKID1234567890
27+
aws_secret_access_key = MY-SECRET-KEY
28+
29+
You can learn more about the credentials file from this [blog post](http://blogs.aws.amazon.com/security/post/Tx3D6U6WSFGOK2H/A-New-and-Standardized-Way-to-Manage-Credentials-in-the-AWS-SDKs).
30+
31+
This is the simplest case, you can then create a new machine with:
32+
33+
$ docker-machine create --driver amazonec2 aws01
34+
35+
### Command line flags
36+
Alternatively, you can use the flags `--amazonec2-access-key` and `--amazonec2-secret-key` on the command line:
2137

2238
$ docker-machine create --driver amazonec2 --amazonec2-access-key AKI******* --amazonec2-secret-key 8T93C******* aws01
2339

40+
### Environment variables
41+
You can use environment variables:
42+
43+
$ export AWS_ACCESS_KEY_ID=AKID1234567890
44+
$ export AWS_SECRET_ACCESS_KEY=MY-SECRET-KEY
45+
$ docker-machine create --driver amazonec2 aws01
46+
2447
## Options
2548

26-
- `--amazonec2-access-key`: **required** Your access key id for the Amazon Web Services API.
27-
- `--amazonec2-secret-key`: **required** Your secret access key for the Amazon Web Services API.
49+
- `--amazonec2-access-key`: Your access key id for the Amazon Web Services API.
50+
- `--amazonec2-secret-key`: Your secret access key for the Amazon Web Services API.
2851
- `--amazonec2-session-token`: Your session token for the Amazon Web Services API.
2952
- `--amazonec2-ami`: The AMI ID of the instance to use.
3053
- `--amazonec2-region`: The region to use when launching the instance.
@@ -66,8 +89,8 @@ Environment variables and default values:
6689

6790
| CLI option | Environment variable | Default |
6891
| ---------------------------------------- | ----------------------- | ---------------- |
69-
| **`--amazonec2-access-key`** | `AWS_ACCESS_KEY_ID` | - |
70-
| **`--amazonec2-secret-key`** | `AWS_SECRET_ACCESS_KEY` | - |
92+
| `--amazonec2-access-key` | `AWS_ACCESS_KEY_ID` | - |
93+
| `--amazonec2-secret-key` | `AWS_SECRET_ACCESS_KEY` | - |
7194
| `--amazonec2-session-token` | `AWS_SESSION_TOKEN` | - |
7295
| `--amazonec2-ami` | `AWS_AMI` | `ami-5f709f34` |
7396
| `--amazonec2-region` | `AWS_DEFAULT_REGION` | `us-east-1` |
@@ -90,8 +113,7 @@ Environment variables and default values:
90113
| `--amazonec2-use-ebs-optimized-instance` | - | `false` |
91114

92115
## Security Group
93-
94-
Note that a security group will be created and associated to the host. This security group will have the following ports opened inbound :
116+
Note that a security group will be created and associated to the host. This security group will have the following ports opened inbound:
95117

96118
- ssh (22/tcp)
97119
- docker (2376/tcp)

drivers/amazonec2/amazonec2.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ const (
4848
var (
4949
dockerPort = 2376
5050
swarmPort = 3376
51-
errorMissingAccessKeyOption = errors.New("amazonec2 driver requires the --amazonec2-access-key option")
52-
errorMissingSecretKeyOption = errors.New("amazonec2 driver requires the --amazonec2-secret-key option")
51+
errorMissingAccessKeyOption = errors.New("amazonec2 driver requires the --amazonec2-access-key option or proper credentials in ~/.aws/credentials")
52+
errorMissingSecretKeyOption = errors.New("amazonec2 driver requires the --amazonec2-secret-key option or proper credentials in ~/.aws/credentials")
5353
errorNoVPCIdFound = errors.New("amazonec2 driver requires either the --amazonec2-subnet-id or --amazonec2-vpc-id option or an AWS Account with a default vpc-id")
5454
)
5555

@@ -285,6 +285,18 @@ func (d *Driver) SetConfigFromFlags(flags drivers.DriverOptions) error {
285285
d.UseEbsOptimizedInstance = flags.Bool("amazonec2-use-ebs-optimized-instance")
286286
d.SetSwarmConfigFromFlags(flags)
287287

288+
if d.AccessKey == "" && d.SecretKey == "" {
289+
credentials, err := d.awsCredentials.NewSharedCredentials("", "").Get()
290+
if err != nil {
291+
log.Debug("Could not load credentials from ~/.aws/credentials")
292+
} else {
293+
log.Debug("Successfully loaded credentials from ~/.aws/credentials")
294+
d.AccessKey = credentials.AccessKeyID
295+
d.SecretKey = credentials.SecretAccessKey
296+
d.SessionToken = credentials.SessionToken
297+
}
298+
}
299+
288300
if d.AccessKey == "" {
289301
return errorMissingAccessKeyOption
290302
}

drivers/amazonec2/amazonec2_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,96 @@ func TestDescribeAccountAttributeFails(t *testing.T) {
282282
assert.Empty(t, vpc)
283283
}
284284

285+
func TestAccessKeyIsMandatory(t *testing.T) {
286+
driver := NewDriver("machineFoo", "path")
287+
driver.clientFactory = func() Ec2Client { return &fakeEC2{} }
288+
driver.awsCredentials = &cliCredentials{}
289+
options := &commandstest.FakeFlagger{
290+
Data: map[string]interface{}{
291+
"name": "test",
292+
"amazonec2-region": "us-east-1",
293+
"amazonec2-zone": "e",
294+
},
295+
}
296+
297+
err := driver.SetConfigFromFlags(options)
298+
299+
assert.Equal(t, err, errorMissingAccessKeyOption)
285300
}
286301

302+
func TestAccessKeyIsMandatoryEvenIfSecretKeyIsPassed(t *testing.T) {
303+
driver := NewDriver("machineFoo", "path")
304+
driver.clientFactory = func() Ec2Client { return &fakeEC2{} }
305+
driver.awsCredentials = &cliCredentials{}
306+
options := &commandstest.FakeFlagger{
307+
Data: map[string]interface{}{
308+
"name": "test",
309+
"amazonec2-secret-key": "123",
310+
"amazonec2-region": "us-east-1",
311+
"amazonec2-zone": "e",
312+
},
313+
}
314+
315+
err := driver.SetConfigFromFlags(options)
316+
317+
assert.Equal(t, err, errorMissingAccessKeyOption)
287318
}
288319

320+
func TestSecretKeyIsMandatory(t *testing.T) {
321+
driver := NewDriver("machineFoo", "path")
322+
driver.clientFactory = func() Ec2Client { return &fakeEC2{} }
323+
driver.awsCredentials = &cliCredentials{}
324+
options := &commandstest.FakeFlagger{
325+
Data: map[string]interface{}{
326+
"name": "test",
327+
"amazonec2-access-key": "foobar",
328+
"amazonec2-region": "us-east-1",
329+
"amazonec2-zone": "e",
330+
},
331+
}
332+
333+
err := driver.SetConfigFromFlags(options)
334+
335+
assert.Equal(t, err, errorMissingSecretKeyOption)
289336
}
290337

338+
func TestLoadingFromCredentialsWorked(t *testing.T) {
339+
driver := NewDriver("machineFoo", "path")
340+
driver.clientFactory = func() Ec2Client { return &fakeEC2WithLogin{} }
341+
driver.awsCredentials = &fileCredentials{}
342+
options := &commandstest.FakeFlagger{
343+
Data: map[string]interface{}{
344+
"name": "test",
345+
"amazonec2-region": "us-east-1",
346+
"amazonec2-zone": "e",
347+
},
348+
}
349+
350+
err := driver.SetConfigFromFlags(options)
351+
352+
assert.NoError(t, err)
353+
assert.Equal(t, "access", driver.AccessKey)
354+
assert.Equal(t, "secret", driver.SecretKey)
355+
assert.Equal(t, "token", driver.SessionToken)
291356
}
292357

358+
func TestPassingBothCLIArgWorked(t *testing.T) {
359+
driver := NewDriver("machineFoo", "path")
360+
driver.clientFactory = func() Ec2Client { return &fakeEC2WithLogin{} }
361+
driver.awsCredentials = &cliCredentials{}
362+
options := &commandstest.FakeFlagger{
363+
Data: map[string]interface{}{
364+
"name": "test",
365+
"amazonec2-access-key": "foobar",
366+
"amazonec2-secret-key": "123",
367+
"amazonec2-region": "us-east-1",
368+
"amazonec2-zone": "e",
369+
},
370+
}
371+
372+
err := driver.SetConfigFromFlags(options)
373+
374+
assert.NoError(t, err)
375+
assert.Equal(t, "foobar", driver.AccessKey)
376+
assert.Equal(t, "123", driver.SecretKey)
377+
}

0 commit comments

Comments
 (0)