func requestCred(client *ec2metadata.EC2Metadata, credsName string) (ec2RoleCredRespBody, error) {
	resp, err := client.GetMetadata(sdkuri.PathJoin(iamSecurityCredsPath, credsName))
	if err != nil {
		return ec2RoleCredRespBody{},
			awserr.New("EC2RoleRequestError",
				fmt.Sprintf("failed to get %s EC2 instance role credentials", credsName),
				err)
	}
	respCreds := ec2RoleCredRespBody{}
	if err := json.NewDecoder(strings.NewReader(resp)).Decode(&respCreds); err != nil {
		return ec2RoleCredRespBody{},
			awserr.New("SerializationError",
				fmt.Sprintf("failed to decode %s EC2 instance role credentials", credsName),
				err)
	}
	if respCreds.Code != "Success" {
		return ec2RoleCredRespBody{}, awserr.New(respCreds.Code, respCreds.Message, nil)
	}
	return respCreds, nil
}
requestCred requests the credentials for a specific credentials from the EC2 service.

If the credentials cannot be found, or there is an error reading the response
and error will be returned.
package ec2rolecreds
import (
	"bufio"
	"encoding/json"
	"fmt"
	"strings"
	"time"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/client"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/ec2metadata"
	"github.com/aws/aws-sdk-go/internal/sdkuri"
)
const ProviderName = "EC2RoleProvider"
type EC2RoleProvider struct {
	credentials.Expiry
	Client *ec2metadata.EC2Metadata
	ExpiryWindow time.Duration
}
func NewCredentials(c client.ConfigProvider, options ...func(*EC2RoleProvider)) *credentials.Credentials {
	p := &EC2RoleProvider{
		Client: ec2metadata.New(c),
	}
	for _, option := range options {
		option(p)
	}
	return credentials.NewCredentials(p)
}
func NewCredentialsWithClient(client *ec2metadata.EC2Metadata, options ...func(*EC2RoleProvider)) *credentials.Credentials {
	p := &EC2RoleProvider{
		Client: client,
	}
	for _, option := range options {
		option(p)
	}
	return credentials.NewCredentials(p)
}
func (m *EC2RoleProvider) Retrieve() (credentials.Value, error) {
	credsList, err := requestCredList(m.Client)
	if err != nil {
		return credentials.Value{ProviderName: ProviderName}, err
	}
	if len(credsList) == 0 {
		return credentials.Value{ProviderName: ProviderName}, awserr.New("EmptyEC2RoleList", "empty EC2 Role list", nil)
	}
	credsName := credsList[0]
	roleCreds, err := requestCred(m.Client, credsName)
	if err != nil {
		return credentials.Value{ProviderName: ProviderName}, err
	}
	m.SetExpiration(roleCreds.Expiration, m.ExpiryWindow)
	return credentials.Value{
		AccessKeyID:     roleCreds.AccessKeyID,
		SecretAccessKey: roleCreds.SecretAccessKey,
		SessionToken:    roleCreds.Token,
		ProviderName:    ProviderName,
	}, nil
}
type ec2RoleCredRespBody struct {
	Expiration      time.Time
	AccessKeyID     string
	SecretAccessKey string
	Token           string
	Code    string
	Message string
}
const iamSecurityCredsPath = "iam/security-credentials/"
func requestCredList(client *ec2metadata.EC2Metadata) ([]string, error) {
	resp, err := client.GetMetadata(iamSecurityCredsPath)
	if err != nil {
		return nil, awserr.New("EC2RoleRequestError", "no EC2 instance role found", err)
	}
	credsList := []string{}
	s := bufio.NewScanner(strings.NewReader(resp))
	for s.Scan() {
		credsList = append(credsList, s.Text())
	}
	if err := s.Err(); err != nil {
		return nil, awserr.New("SerializationError", "failed to read EC2 instance role from metadata service", err)
	}
	return credsList, nil
}