Blame vendor/github.com/aws/aws-sdk-go/aws/ec2metadata/service.go

Packit 63bb0d
// Package ec2metadata provides the client for making API calls to the
Packit 63bb0d
// EC2 Metadata service.
Packit 63bb0d
//
Packit 63bb0d
// This package's client can be disabled completely by setting the environment
Packit 63bb0d
// variable "AWS_EC2_METADATA_DISABLED=true". This environment variable set to
Packit 63bb0d
// true instructs the SDK to disable the EC2 Metadata client. The client cannot
Packit 63bb0d
// be used while the environment variable is set to true, (case insensitive).
Packit 63bb0d
package ec2metadata
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"bytes"
Packit 63bb0d
	"errors"
Packit 63bb0d
	"io"
Packit 63bb0d
	"net/http"
Packit 63bb0d
	"os"
Packit 63bb0d
	"strings"
Packit 63bb0d
	"time"
Packit 63bb0d
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/awserr"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/client"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/client/metadata"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/corehandlers"
Packit 63bb0d
	"github.com/aws/aws-sdk-go/aws/request"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
// ServiceName is the name of the service.
Packit 63bb0d
const ServiceName = "ec2metadata"
Packit 63bb0d
const disableServiceEnvVar = "AWS_EC2_METADATA_DISABLED"
Packit 63bb0d
Packit 63bb0d
// A EC2Metadata is an EC2 Metadata service Client.
Packit 63bb0d
type EC2Metadata struct {
Packit 63bb0d
	*client.Client
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// New creates a new instance of the EC2Metadata client with a session.
Packit 63bb0d
// This client is safe to use across multiple goroutines.
Packit 63bb0d
//
Packit 63bb0d
//
Packit 63bb0d
// Example:
Packit 63bb0d
//     // Create a EC2Metadata client from just a session.
Packit 63bb0d
//     svc := ec2metadata.New(mySession)
Packit 63bb0d
//
Packit 63bb0d
//     // Create a EC2Metadata client with additional configuration
Packit 63bb0d
//     svc := ec2metadata.New(mySession, aws.NewConfig().WithLogLevel(aws.LogDebugHTTPBody))
Packit 63bb0d
func New(p client.ConfigProvider, cfgs ...*aws.Config) *EC2Metadata {
Packit 63bb0d
	c := p.ClientConfig(ServiceName, cfgs...)
Packit 63bb0d
	return NewClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// NewClient returns a new EC2Metadata client. Should be used to create
Packit 63bb0d
// a client when not using a session. Generally using just New with a session
Packit 63bb0d
// is preferred.
Packit 63bb0d
//
Packit 63bb0d
// If an unmodified HTTP client is provided from the stdlib default, or no client
Packit 63bb0d
// the EC2RoleProvider's EC2Metadata HTTP client's timeout will be shortened.
Packit 63bb0d
// To disable this set Config.EC2MetadataDisableTimeoutOverride to false. Enabled by default.
Packit 63bb0d
func NewClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion string, opts ...func(*client.Client)) *EC2Metadata {
Packit 63bb0d
	if !aws.BoolValue(cfg.EC2MetadataDisableTimeoutOverride) && httpClientZero(cfg.HTTPClient) {
Packit 63bb0d
		// If the http client is unmodified and this feature is not disabled
Packit 63bb0d
		// set custom timeouts for EC2Metadata requests.
Packit 63bb0d
		cfg.HTTPClient = &http.Client{
Packit 63bb0d
			// use a shorter timeout than default because the metadata
Packit 63bb0d
			// service is local if it is running, and to fail faster
Packit 63bb0d
			// if not running on an ec2 instance.
Packit 63bb0d
			Timeout: 5 * time.Second,
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	svc := &EC2Metadata{
Packit 63bb0d
		Client: client.New(
Packit 63bb0d
			cfg,
Packit 63bb0d
			metadata.ClientInfo{
Packit 63bb0d
				ServiceName: ServiceName,
Packit 63bb0d
				ServiceID:   ServiceName,
Packit 63bb0d
				Endpoint:    endpoint,
Packit 63bb0d
				APIVersion:  "latest",
Packit 63bb0d
			},
Packit 63bb0d
			handlers,
Packit 63bb0d
		),
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	svc.Handlers.Unmarshal.PushBack(unmarshalHandler)
Packit 63bb0d
	svc.Handlers.UnmarshalError.PushBack(unmarshalError)
Packit 63bb0d
	svc.Handlers.Validate.Clear()
Packit 63bb0d
	svc.Handlers.Validate.PushBack(validateEndpointHandler)
Packit 63bb0d
Packit 63bb0d
	// Disable the EC2 Metadata service if the environment variable is set.
Packit 63bb0d
	// This shortcirctes the service's functionality to always fail to send
Packit 63bb0d
	// requests.
Packit 63bb0d
	if strings.ToLower(os.Getenv(disableServiceEnvVar)) == "true" {
Packit 63bb0d
		svc.Handlers.Send.SwapNamed(request.NamedHandler{
Packit 63bb0d
			Name: corehandlers.SendHandler.Name,
Packit 63bb0d
			Fn: func(r *request.Request) {
Packit 63bb0d
				r.HTTPResponse = &http.Response{
Packit 63bb0d
					Header: http.Header{},
Packit 63bb0d
				}
Packit 63bb0d
				r.Error = awserr.New(
Packit 63bb0d
					request.CanceledErrorCode,
Packit 63bb0d
					"EC2 IMDS access disabled via "+disableServiceEnvVar+" env var",
Packit 63bb0d
					nil)
Packit 63bb0d
			},
Packit 63bb0d
		})
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// Add additional options to the service config
Packit 63bb0d
	for _, option := range opts {
Packit 63bb0d
		option(svc.Client)
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	return svc
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func httpClientZero(c *http.Client) bool {
Packit 63bb0d
	return c == nil || (c.Transport == nil && c.CheckRedirect == nil && c.Jar == nil && c.Timeout == 0)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
type metadataOutput struct {
Packit 63bb0d
	Content string
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func unmarshalHandler(r *request.Request) {
Packit 63bb0d
	defer r.HTTPResponse.Body.Close()
Packit 63bb0d
	b := &bytes.Buffer{}
Packit 63bb0d
	if _, err := io.Copy(b, r.HTTPResponse.Body); err != nil {
Packit 63bb0d
		r.Error = awserr.New(request.ErrCodeSerialization, "unable to unmarshal EC2 metadata response", err)
Packit 63bb0d
		return
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if data, ok := r.Data.(*metadataOutput); ok {
Packit 63bb0d
		data.Content = b.String()
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func unmarshalError(r *request.Request) {
Packit 63bb0d
	defer r.HTTPResponse.Body.Close()
Packit 63bb0d
	b := &bytes.Buffer{}
Packit 63bb0d
	if _, err := io.Copy(b, r.HTTPResponse.Body); err != nil {
Packit 63bb0d
		r.Error = awserr.New(request.ErrCodeSerialization, "unable to unmarshal EC2 metadata error response", err)
Packit 63bb0d
		return
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	// Response body format is not consistent between metadata endpoints.
Packit 63bb0d
	// Grab the error message as a string and include that as the source error
Packit 63bb0d
	r.Error = awserr.New("EC2MetadataError", "failed to make EC2Metadata request", errors.New(b.String()))
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func validateEndpointHandler(r *request.Request) {
Packit 63bb0d
	if r.ClientInfo.Endpoint == "" {
Packit 63bb0d
		r.Error = aws.ErrMissingEndpoint
Packit 63bb0d
	}
Packit 63bb0d
}