github.com/webdestroya/awsmocker@v0.2.6/imds_mocks.go (about)

     1  package awsmocker
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"time"
     7  
     8  	"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
     9  )
    10  
    11  // Override the default settings when using a default IMDS mock
    12  type IMDSMockOptions struct {
    13  	// The identity document to return
    14  	IdentityDocument imds.InstanceIdentityDocument
    15  
    16  	// any custom user data
    17  	UserData string
    18  
    19  	// if you want to override the role name that is used for EC2 creds
    20  	RoleName string
    21  
    22  	// Override the instance profile name
    23  	InstanceProfileName string
    24  }
    25  
    26  func getDefaultImdsIdentityDocument() imds.InstanceIdentityDocument {
    27  	return imds.InstanceIdentityDocument{
    28  		Version:          "2017-09-30",
    29  		InstanceID:       "i-000deadbeef",
    30  		AccountID:        DefaultAccountId,
    31  		Region:           DefaultRegion,
    32  		AvailabilityZone: DefaultRegion + "a",
    33  		InstanceType:     "t3.medium",
    34  	}
    35  }
    36  
    37  // Provides an array of mocks that will provide a decent replication of the
    38  // EC2 Instance Metadata Service
    39  func Mock_IMDS_Common(optFns ...func(*IMDSMockOptions)) []*MockedEndpoint {
    40  
    41  	cfg := IMDSMockOptions{
    42  		IdentityDocument:    getDefaultImdsIdentityDocument(),
    43  		UserData:            "# awsmocker",
    44  		RoleName:            "awsmocker_role",
    45  		InstanceProfileName: "awsmocker-instance-profile",
    46  	}
    47  
    48  	for _, f := range optFns {
    49  		f(&cfg)
    50  	}
    51  
    52  	mocks := make([]*MockedEndpoint, 0, 10)
    53  
    54  	mocks = append(mocks, Mock_IMDS_IdentityDocument(func(iid *imds.InstanceIdentityDocument) {
    55  		*iid = cfg.IdentityDocument
    56  	}))
    57  
    58  	for k, v := range map[string]string{
    59  		"instance-id":         cfg.IdentityDocument.InstanceID,
    60  		"instance-type":       cfg.IdentityDocument.InstanceType,
    61  		"instance-life-cycle": "on-demand",
    62  	} {
    63  		mocks = append(mocks, Mock_IMDS_MetaData_KeyValue(k, v))
    64  	}
    65  
    66  	mocks = append(mocks, Mock_IMDS_UserData(cfg.UserData))
    67  	mocks = append(mocks, Mock_IMDS_IAM_Info(cfg.InstanceProfileName))
    68  	mocks = append(mocks, Mock_IMDS_IAM_RoleList(cfg.RoleName))
    69  	mocks = append(mocks, Mock_IMDS_IAM_Credentials(cfg.RoleName))
    70  	mocks = append(mocks, Mock_IMDS_API_Token())
    71  
    72  	return mocks
    73  }
    74  
    75  // Provide a document to be returned, or nil to use a default one
    76  func Mock_IMDS_IdentityDocument(optFns ...func(*imds.InstanceIdentityDocument)) *MockedEndpoint {
    77  	doc := getDefaultImdsIdentityDocument()
    78  
    79  	for _, f := range optFns {
    80  		f(&doc)
    81  	}
    82  
    83  	return &MockedEndpoint{
    84  		Request: &MockedRequest{
    85  			Method:    http.MethodGet,
    86  			Path:      "/latest/dynamic/instance-identity/document",
    87  			IsEc2IMDS: true,
    88  		},
    89  		Response: &MockedResponse{
    90  			Encoding: ResponseEncodingJSON,
    91  			Body:     doc,
    92  		},
    93  	}
    94  }
    95  
    96  func Mock_IMDS_MetaData_KeyValue(k, v string) *MockedEndpoint {
    97  	return &MockedEndpoint{
    98  		Request: &MockedRequest{
    99  			Method:    http.MethodGet,
   100  			Path:      "/latest/meta-data/" + k,
   101  			IsEc2IMDS: true,
   102  		},
   103  		Response: &MockedResponse{
   104  			Encoding: ResponseEncodingText,
   105  			Body:     v,
   106  		},
   107  	}
   108  }
   109  
   110  func Mock_IMDS_UserData(userData string) *MockedEndpoint {
   111  	return &MockedEndpoint{
   112  		Request: &MockedRequest{
   113  			Method:    http.MethodGet,
   114  			Path:      "/latest/user-data",
   115  			IsEc2IMDS: true,
   116  		},
   117  		Response: &MockedResponse{
   118  			Encoding: ResponseEncodingText,
   119  			Body:     userData,
   120  		},
   121  	}
   122  }
   123  
   124  func Mock_IMDS_API_Token() *MockedEndpoint {
   125  	return &MockedEndpoint{
   126  		Request: &MockedRequest{
   127  			Path:      "/latest/api/token",
   128  			IsEc2IMDS: true,
   129  		},
   130  		Response: &MockedResponse{
   131  			Encoding: ResponseEncodingText,
   132  			Body:     "AwsMockerImdsToken",
   133  		},
   134  	}
   135  }
   136  
   137  func Mock_IMDS_IAM_Info(profileName string) *MockedEndpoint {
   138  	return &MockedEndpoint{
   139  		Request: &MockedRequest{
   140  			Method:    http.MethodGet,
   141  			Path:      "/latest/meta-data/iam/info",
   142  			IsEc2IMDS: true,
   143  		},
   144  		Response: &MockedResponse{
   145  			Encoding: ResponseEncodingJSON,
   146  			Body: map[string]interface{}{
   147  				"Code":               "Success",
   148  				"LastUpdated":        time.Now().UTC().Format(time.RFC3339),
   149  				"InstanceProfileArn": fmt.Sprintf("arn:aws:iam::%s:instance-profile/%s", DefaultAccountId, profileName),
   150  				"InstanceProfileId":  "AIPAABCDEFGHIJKLMN123",
   151  			},
   152  		},
   153  	}
   154  }
   155  
   156  func Mock_IMDS_IAM_RoleList(roleName string) *MockedEndpoint {
   157  	return &MockedEndpoint{
   158  		Request: &MockedRequest{
   159  			Method:    http.MethodGet,
   160  			Path:      "/latest/meta-data/iam/security-credentials/",
   161  			IsEc2IMDS: true,
   162  		},
   163  		Response: &MockedResponse{
   164  			Encoding: ResponseEncodingText,
   165  			Body:     roleName,
   166  		},
   167  	}
   168  }
   169  
   170  func Mock_IMDS_IAM_Credentials(roleName string) *MockedEndpoint {
   171  	return &MockedEndpoint{
   172  		Request: &MockedRequest{
   173  			Method: http.MethodGet,
   174  			Path:   "/latest/meta-data/iam/security-credentials/" + roleName,
   175  		},
   176  		Response: &MockedResponse{
   177  			Encoding: ResponseEncodingJSON,
   178  			Body: map[string]interface{}{
   179  				"Code":            "Success",
   180  				"Type":            "AWS-HMAC",
   181  				"LastUpdated":     time.Now().UTC().Format(time.RFC3339),
   182  				"Expiration":      time.Now().UTC().Add(1 * time.Hour).Format(time.RFC3339),
   183  				"AccessKeyID":     "FAKEKEY",
   184  				"SecretAccessKey": "fakeSecretKEY",
   185  				"Token":           "FAKETOKEN",
   186  			},
   187  		},
   188  	}
   189  }