Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use RemoteCredProvider instead of EC2RoleProvider #2983

Merged
merged 4 commits into from
Jul 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you also want to check AWS_DEFAULT_REGION here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

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`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this incorrect before?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep. Looks like it was copypasta. The code actually uses AWS_S3_ENDPOINT though.


- `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 @@ -43,10 +43,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