Add support for AWS instance metadata v2 (#8062)

* add support for aws instance metadata v2

* use GetDynamicData instead
This commit is contained in:
Becca Petrin 2020-01-10 09:31:16 -08:00 committed by GitHub
parent 156e31c740
commit 6291c75175
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 53 deletions

View File

@ -5,17 +5,16 @@ import (
"encoding/base64"
"errors"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"sync"
"time"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/hashicorp/errwrap"
cleanhttp "github.com/hashicorp/go-cleanhttp"
hclog "github.com/hashicorp/go-hclog"
uuid "github.com/hashicorp/go-uuid"
"github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/api"
awsauth "github.com/hashicorp/vault/builtin/credential/aws"
"github.com/hashicorp/vault/command/agent/auth"
@ -23,9 +22,8 @@ import (
)
const (
typeEC2 = "ec2"
typeIAM = "iam"
identityEndpoint = "http://169.254.169.254/latest/dynamic/instance-identity"
typeEC2 = "ec2"
typeIAM = "iam"
/*
@ -183,61 +181,33 @@ func (a *awsMethod) Authenticate(ctx context.Context, client *api.Client) (retTo
a.logger.Trace("beginning authentication")
data := make(map[string]interface{})
sess, err := session.NewSession()
if err != nil {
retErr = errwrap.Wrapf("error creating session: {{err}}", err)
return
}
metadataSvc := ec2metadata.New(sess)
switch a.authType {
case typeEC2:
client := cleanhttp.DefaultClient()
// Fetch document
{
req, err := http.NewRequest("GET", fmt.Sprintf("%s/document", identityEndpoint), nil)
doc, err := metadataSvc.GetDynamicData("/instance-identity/document")
if err != nil {
retErr = errwrap.Wrapf("error creating request: {{err}}", err)
retErr = errwrap.Wrapf("error requesting doc: {{err}}", err)
return
}
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err != nil {
retErr = errwrap.Wrapf("error fetching instance document: {{err}}", err)
return
}
if resp == nil {
retErr = errors.New("empty response fetching instance document")
return
}
defer resp.Body.Close()
doc, err := ioutil.ReadAll(resp.Body)
if err != nil {
retErr = errwrap.Wrapf("error reading instance document response body: {{err}}", err)
return
}
data["identity"] = base64.StdEncoding.EncodeToString(doc)
data["identity"] = base64.StdEncoding.EncodeToString([]byte(doc))
}
// Fetch signature
{
req, err := http.NewRequest("GET", fmt.Sprintf("%s/signature", identityEndpoint), nil)
signature, err := metadataSvc.GetDynamicData("/instance-identity/signature")
if err != nil {
retErr = errwrap.Wrapf("error creating request: {{err}}", err)
retErr = errwrap.Wrapf("error requesting signature: {{err}}", err)
return
}
req = req.WithContext(ctx)
resp, err := client.Do(req)
if err != nil {
retErr = errwrap.Wrapf("error fetching instance document signature: {{err}}", err)
return
}
if resp == nil {
retErr = errors.New("empty response fetching instance document signature")
return
}
defer resp.Body.Close()
sig, err := ioutil.ReadAll(resp.Body)
if err != nil {
retErr = errwrap.Wrapf("error reading instance document signature response body: {{err}}", err)
return
}
data["signature"] = string(sig)
data["signature"] = signature
}
// Add the reauthentication value, if we have one

View File

@ -15,7 +15,8 @@ import (
// is a widely used region, and is the most common one for some services like STS.
const DefaultRegion = "us-east-1"
var ec2MetadataBaseURL = "http://169.254.169.254"
// This is nil by default, but is exposed in case it needs to be changed for tests.
var ec2Endpoint *string = nil
/*
It's impossible to mimic "normal" AWS behavior here because it's not consistent
@ -56,7 +57,7 @@ func GetOrDefaultRegion(logger hclog.Logger, configuredRegion string) string {
}
metadata := ec2metadata.New(sess, &aws.Config{
Endpoint: aws.String(ec2MetadataBaseURL + "/latest"),
Endpoint: ec2Endpoint,
EC2MetadataDisableTimeoutOverride: aws.Bool(true),
HTTPClient: &http.Client{
Timeout: time.Second,

View File

@ -9,6 +9,7 @@ import (
"os/user"
"testing"
"github.com/aws/aws-sdk-go/aws"
hclog "github.com/hashicorp/go-hclog"
)
@ -240,11 +241,10 @@ func setInstanceMetadata(t *testing.T, region string) (cleanup func()) {
t.Fatalf("received unexpected request path: %s", reqPath)
}
}))
originalMetadataBaseURL := ec2MetadataBaseURL
ec2MetadataBaseURL = ts.URL
ec2Endpoint = aws.String(ts.URL)
cleanup = func() {
ts.Close()
ec2MetadataBaseURL = originalMetadataBaseURL
ec2Endpoint = nil
}
return
}