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
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
@@ -2,6 +2,7 @@ package aws

import (
"fmt"
"os"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
@@ -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()
3 changes: 0 additions & 3 deletions builtin/logical/aws/path_config_root.go
Original file line number Diff line number Diff line change
@@ -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),
20 changes: 9 additions & 11 deletions helper/awsutil/generate_credentials.go
Original file line number Diff line number Diff line change
@@ -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 {
@@ -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)
43 changes: 26 additions & 17 deletions physical/dynamodb.go
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@ package physical
import (
"fmt"
"math"
"net/http"
"os"
pkgPath "path"
"sort"
@@ -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 (
@@ -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 {
9 changes: 6 additions & 3 deletions physical/s3.go
Original file line number Diff line number Diff line change
@@ -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"
}
}
}

12 changes: 9 additions & 3 deletions website/source/api/secret/aws/index.html.md
Original file line number Diff line number Diff line change
@@ -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.
@@ -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

8 changes: 4 additions & 4 deletions website/source/docs/auth/aws.html.md
Original file line number Diff line number Diff line change
@@ -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 \
5 changes: 3 additions & 2 deletions website/source/docs/configuration/storage/s3.html.md
Original file line number Diff line number Diff line change
@@ -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
12 changes: 9 additions & 3 deletions website/source/docs/secrets/aws/index.html.md
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 54e3d61

Please sign in to comment.