Skip to content

Commit

Permalink
Use RemoteCredProvider instead of EC2RoleProvider (#2983)
Browse files Browse the repository at this point in the history
  • Loading branch information
jefferai authored Jul 31, 2017
1 parent 95ce578 commit 54e3d61
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 47 deletions.
9 changes: 8 additions & 1 deletion builtin/logical/aws/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package aws

import (
"fmt"
"os"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
Expand Down Expand Up @@ -31,7 +32,13 @@ func getRootConfig(s logical.Storage) (*aws.Config, error) {
}

if credsConfig.Region == "" {
credsConfig.Region = "us-east-1"
credsConfig.Region = os.Getenv("AWS_REGION")
if credsConfig.Region == "" {
credsConfig.Region = os.Getenv("AWS_DEFAULT_REGION")
if credsConfig.Region == "" {
credsConfig.Region = "us-east-1"
}
}
}

credsConfig.HTTPClient = cleanhttp.DefaultClient()
Expand Down
3 changes: 0 additions & 3 deletions builtin/logical/aws/path_config_root.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ func pathConfigRoot() *framework.Path {
func pathConfigRootWrite(
req *logical.Request, data *framework.FieldData) (*logical.Response, error) {
region := data.Get("region").(string)
if region == "" {
region = "us-east-1"
}

entry, err := logical.StorageEntryJSON("config/root", rootConfig{
AccessKey: data.Get("access_key").(string),
Expand Down
20 changes: 9 additions & 11 deletions helper/awsutil/generate_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import (

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/aws/defaults"
)

type CredentialsConfig struct {
Expand Down Expand Up @@ -65,14 +63,14 @@ func (c *CredentialsConfig) GenerateCredentialChain() (*credentials.Credentials,
Profile: c.Profile,
})

// Add the instance metadata role provider
providers = append(providers, &ec2rolecreds.EC2RoleProvider{
Client: ec2metadata.New(session.New(&aws.Config{
Region: aws.String(c.Region),
HTTPClient: c.HTTPClient,
})),
ExpiryWindow: 15,
})
// Add the remote provider
def := defaults.Get()
if c.Region != "" {
def.Config.Region = aws.String(c.Region)
}
def.Config.HTTPClient = c.HTTPClient

providers = append(providers, defaults.RemoteCredProvider(*def.Config, def.Handlers))

// Create the credentials required to access the API.
creds := credentials.NewChainCredentials(providers)
Expand Down
43 changes: 26 additions & 17 deletions physical/dynamodb.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package physical
import (
"fmt"
"math"
"net/http"
"os"
pkgPath "path"
"sort"
Expand All @@ -16,14 +17,14 @@ import (
"github.com/armon/go-metrics"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/dynamodb"
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/hashicorp/errwrap"
cleanhttp "github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/helper/awsutil"
"github.com/hashicorp/vault/helper/consts"
)

const (
Expand Down Expand Up @@ -166,29 +167,37 @@ func newDynamoDBBackend(conf map[string]string, logger log.Logger) (Backend, err
if endpoint == "" {
endpoint = conf["endpoint"]
}
region := os.Getenv("AWS_DEFAULT_REGION")
region := os.Getenv("AWS_REGION")
if region == "" {
region = conf["region"]
region = os.Getenv("AWS_DEFAULT_REGION")
if region == "" {
region = DefaultDynamoDBRegion
region = conf["region"]
if region == "" {
region = DefaultDynamoDBRegion
}
}
}

creds := credentials.NewChainCredentials([]credentials.Provider{
&credentials.StaticProvider{Value: credentials.Value{
AccessKeyID: accessKey,
SecretAccessKey: secretKey,
SessionToken: sessionToken,
}},
&credentials.EnvProvider{},
&credentials.SharedCredentialsProvider{Filename: "", Profile: ""},
&ec2rolecreds.EC2RoleProvider{Client: ec2metadata.New(session.New())},
})
credsConfig := &awsutil.CredentialsConfig{
AccessKey: accessKey,
SecretKey: secretKey,
SessionToken: sessionToken,
}
creds, err := credsConfig.GenerateCredentialChain()
if err != nil {
return nil, err
}

pooledTransport := cleanhttp.DefaultPooledTransport()
pooledTransport.MaxIdleConnsPerHost = consts.ExpirationRestoreWorkerCount

awsConf := aws.NewConfig().
WithCredentials(creds).
WithRegion(region).
WithEndpoint(endpoint)
WithEndpoint(endpoint).
WithHTTPClient(&http.Client{
Transport: pooledTransport,
})
client := dynamodb.New(session.New(awsConf))

if err := ensureTableExists(client, table, readCapacity, writeCapacity); err != nil {
Expand Down
9 changes: 6 additions & 3 deletions physical/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,14 @@ func newS3Backend(conf map[string]string, logger log.Logger) (Backend, error) {
if endpoint == "" {
endpoint = conf["endpoint"]
}
region := os.Getenv("AWS_DEFAULT_REGION")
region := os.Getenv("AWS_REGION")
if region == "" {
region = conf["region"]
region = os.Getenv("AWS_DEFAULT_REGION")
if region == "" {
region = "us-east-1"
region = conf["region"]
if region == "" {
region = "us-east-1"
}
}
}

Expand Down
12 changes: 9 additions & 3 deletions website/source/api/secret/aws/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ are multiple ways to pass root IAM credentials to the Vault server, specified
below with the highest precedence first. If credentials already exist, this will
overwrite them.

The official AWS SDK is used for sourcing credentials from env vars, shared
files, or IAM/ECS instances.

- Static credentials provided to the API as a payload

- Credentials in the `AWS_ACCESS_KEY`, `AWS_SECRET_KEY`, and `AWS_REGION`
environment variables **on the server**

- Querying the EC2 metadata service if the **Vault server** is on EC2 and has
querying capabilities
- Shared credentials files

- Assigned IAM role or ECS task role credentials

At present, this endpoint does not confirm that the provided AWS credentials are
valid AWS credentials with proper permissions.
Expand All @@ -44,7 +48,9 @@ valid AWS credentials with proper permissions.

- `secret_key` `(string: <required>)` – Specifies the AWS secret access key.

- `region` `(string: <required>)` – Specifies the AWS region.
- `region` `(string: <optional>)` – Specifies the AWS region. If not set it
will use the `AWS_REGION` env var, `AWS_DEFAULT_REGION` env var, or
`us-east-1` in that order.

### Sample Payload

Expand Down
8 changes: 4 additions & 4 deletions website/source/docs/auth/aws.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -546,10 +546,10 @@ $ vault auth -method=aws header_value=vault.example.com role=dev-role-iam

This assumes you have AWS credentials configured in the standard locations AWS
SDKs search for credentials (environment variables, ~/.aws/credentials, IAM
instance profile in that order). If you do not have IAM credentials available at
any of these locations, you can explicitly pass them in on the command line
(though this is not recommended), omitting `aws_security_token` if not
applicable .
instance profile, or ECS task role, in that order). If you do not have IAM
credentials available at any of these locations, you can explicitly pass them
in on the command line (though this is not recommended), omitting
`aws_security_token` if not applicable.

```
$ vault auth -method=aws header_value=vault.example.com role=dev-role-iam \
Expand Down
5 changes: 3 additions & 2 deletions website/source/docs/configuration/storage/s3.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ storage "s3" {

- `endpoint` `(string: "")` – Specifies an alternative, AWS compatible, S3
endpoint. This can also be provided via the environment variable
`AWS_DEFAULT_REGION`.
`AWS_S3_ENDPOINT`.

- `region` `(string "us-east-1")` – Specifies the AWS region. This can also be
provided via the environment variable `AWS_DEFAULT_REGION`.
provided via the environment variable `AWS_REGION` or `AWS_DEFAULT_REGION`,
in that order of preference.

The following settings are used for authenticating to AWS. If you are
running your Vault server on an EC2 instance, you can also make use of the EC2
Expand Down
12 changes: 9 additions & 3 deletions website/source/docs/secrets/aws/index.html.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,16 @@ The following parameters are required:
credentials.
- `secret_key` - the AWS secret key that has permission to manage IAM
credentials.
- `region` the AWS region for API calls.

Note: the client uses the official AWS SDK and will use environment variable or IAM
role-provided credentials if available.
The following parameter is optional:

- `region` the AWS region for API calls. If not provided, the `AWS_REGION` and
`AWS_DEFAULT_REGION` env vars will be used, in that order. If there is still
no region, `us-east-1` will be used as a fallback.

Note: the client uses the official AWS SDK and will use the specified
credentials, environment credentials, shared file credentials, or IAM role/ECS
task credentials in that order.

The next step is to configure a role. A role is a logical name that maps
to a policy used to generated those credentials.
Expand Down

0 comments on commit 54e3d61

Please sign in to comment.