Add support for AWS instance metadata v2 (#8062)
* add support for aws instance metadata v2 * use GetDynamicData instead
This commit is contained in:
parent
156e31c740
commit
6291c75175
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue