Skip to content

Commit

Permalink
Merge pull request #4274 from wyike/disable-imdsv2
Browse files Browse the repository at this point in the history
Set IMDSv2 as optional
  • Loading branch information
k8s-ci-robot committed May 19, 2023
2 parents 11b3269 + 2bca14c commit b568361
Show file tree
Hide file tree
Showing 11 changed files with 36 additions and 25 deletions.
4 changes: 2 additions & 2 deletions api/v1beta2/awsmachinetemplate_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ func TestAWSMachineTemplateValidateUpdate(t *testing.T) {
InstanceType: "test",
InstanceMetadataOptions: &InstanceMetadataOptions{
HTTPEndpoint: InstanceMetadataEndpointStateEnabled,
HTTPPutResponseHopLimit: 2,
HTTPTokens: HTTPTokensStateRequired,
HTTPPutResponseHopLimit: 1,
HTTPTokens: HTTPTokensStateOptional,
InstanceMetadataTags: InstanceMetadataEndpointStateDisabled,
},
},
Expand Down
10 changes: 6 additions & 4 deletions api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,10 @@ type InstanceMetadataOptions struct {
// always returns the version 2.0 credentials; the version 1.0 credentials are
// not available.
//
// Default: required
// Default: optional
//
// +kubebuilder:validation:Enum:=optional;required
// +kubebuilder:default=required
// +kubebuilder:default=optional
HTTPTokens HTTPTokensState `json:"httpTokens,omitempty"`

// Set to enabled to allow access to instance tags from the instance metadata.
Expand All @@ -275,6 +276,7 @@ type InstanceMetadataOptions struct {
// (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS).
//
// Default: disabled
//
// +kubebuilder:validation:Enum:=enabled;disabled
// +kubebuilder:default=disabled
InstanceMetadataTags InstanceMetadataState `json:"instanceMetadataTags,omitempty"`
Expand All @@ -285,10 +287,10 @@ func (obj *InstanceMetadataOptions) SetDefaults() {
obj.HTTPEndpoint = InstanceMetadataEndpointStateEnabled
}
if obj.HTTPPutResponseHopLimit == 0 {
obj.HTTPPutResponseHopLimit = 2 // Defaults to 2 in container environment
obj.HTTPPutResponseHopLimit = 1
}
if obj.HTTPTokens == "" {
obj.HTTPTokens = HTTPTokensStateRequired // Defaults to IMDSv2
obj.HTTPTokens = HTTPTokensStateOptional // Defaults to IMDSv1
}
if obj.InstanceMetadataTags == "" {
obj.InstanceMetadataTags = InstanceMetadataEndpointStateDisabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ spec:
minimum: 1
type: integer
httpTokens:
default: required
default: optional
description: "The state of token usage for your instance metadata
requests. \n If the state is optional, you can choose to
retrieve instance metadata with or without a session token
Expand All @@ -878,7 +878,7 @@ spec:
with any instance metadata retrieval requests. In this state,
retrieving the IAM role credentials always returns the version
2.0 credentials; the version 1.0 credentials are not available.
\n Default: required"
\n Default: optional"
enum:
- optional
- required
Expand Down Expand Up @@ -2288,7 +2288,7 @@ spec:
minimum: 1
type: integer
httpTokens:
default: required
default: optional
description: "The state of token usage for your instance metadata
requests. \n If the state is optional, you can choose to
retrieve instance metadata with or without a session token
Expand All @@ -2300,7 +2300,7 @@ spec:
with any instance metadata retrieval requests. In this state,
retrieving the IAM role credentials always returns the version
2.0 credentials; the version 1.0 credentials are not available.
\n Default: required"
\n Default: optional"
enum:
- optional
- required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1358,7 +1358,7 @@ spec:
minimum: 1
type: integer
httpTokens:
default: required
default: optional
description: "The state of token usage for your instance metadata
requests. \n If the state is optional, you can choose to
retrieve instance metadata with or without a session token
Expand All @@ -1370,7 +1370,7 @@ spec:
with any instance metadata retrieval requests. In this state,
retrieving the IAM role credentials always returns the version
2.0 credentials; the version 1.0 credentials are not available.
\n Default: required"
\n Default: optional"
enum:
- optional
- required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,7 @@ spec:
minimum: 1
type: integer
httpTokens:
default: required
default: optional
description: "The state of token usage for your instance metadata
requests. \n If the state is optional, you can choose to retrieve
instance metadata with or without a session token on your request.
Expand All @@ -699,7 +699,7 @@ spec:
you must send a session token with any instance metadata retrieval
requests. In this state, retrieving the IAM role credentials
always returns the version 2.0 credentials; the version 1.0
credentials are not available. \n Default: required"
credentials are not available. \n Default: optional"
enum:
- optional
- required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,7 +637,7 @@ spec:
minimum: 1
type: integer
httpTokens:
default: required
default: optional
description: "The state of token usage for your instance
metadata requests. \n If the state is optional, you
can choose to retrieve instance metadata with or without
Expand All @@ -650,7 +650,7 @@ spec:
metadata retrieval requests. In this state, retrieving
the IAM role credentials always returns the version
2.0 credentials; the version 1.0 credentials are not
available. \n Default: required"
available. \n Default: optional"
enum:
- optional
- required
Expand Down
4 changes: 2 additions & 2 deletions controllers/awsmachine_controller_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2551,8 +2551,8 @@ func TestAWSMachineReconcilerReconcileDefaultsToLoadBalancerTypeClassic(t *testi
},
MetadataOptions: &ec2.InstanceMetadataOptionsResponse{
HttpEndpoint: aws.String(string(infrav1.InstanceMetadataEndpointStateEnabled)),
HttpPutResponseHopLimit: aws.Int64(2),
HttpTokens: aws.String(string(infrav1.HTTPTokensStateRequired)),
HttpPutResponseHopLimit: aws.Int64(1),
HttpTokens: aws.String(string(infrav1.HTTPTokensStateOptional)),
InstanceMetadataTags: aws.String(string(infrav1.InstanceMetadataEndpointStateDisabled)),
},
},
Expand Down
16 changes: 11 additions & 5 deletions docs/book/src/topics/instance-metadata.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ Instance metadata is data about your instance that you can use to configure or m
* Instance Metadata Service Version 1 (IMDSv1) – a request/response method
* Instance Metadata Service Version 2 (IMDSv2) – a session-oriented method

CAPA defaults to IMDSv2 when creating instances, as it provides a [better level of security](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/).
CAPA defaults to 2 hot limit when creating instances with IMDSv2, as it is recommended in container environment according to [AWS document](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#imds-considerations).
CAPA defaults to use IMDSv2 as optional property when creating instances.

CAPA expose options to configure IMDSv2 as required when creating instances, as it provides a [better level of security](https://aws.amazon.com/blogs/security/defense-in-depth-open-firewalls-reverse-proxies-ssrf-vulnerabilities-ec2-instance-metadata-service/).

It is possible to configure the instance metadata options using the field called `instanceMetadataOptions` in the `AWSMachineTemplate`.

Expand All @@ -22,11 +23,16 @@ spec:
spec:
instanceMetadataOptions:
httpEndpoint: enabled
httpPutResponseHopLimit: 2
httpTokens: required
httpPutResponseHopLimit: 1
httpTokens: optional
instanceMetadataTags: disabled
```
To use IMDSv1, simply set `httpTokens` value to `optional` (in other words, set the use of IMDSv2 to optional).
To use IMDSv2, simply set `httpTokens` value to `required` (in other words, set the use of IMDSv2 to required).
To use IMDSv2, please also set `httpPutResponseHopLimit` value to `2`, as it is recommended in container environment according to [AWS document](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html#imds-considerations).

See [the CLI command reference](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/modify-instance-metadata-options.html) for more information.

Before you decide to use IMDSv2 for the cluster instances, please make sure all your applications are compatible to IMDSv2.

See the [transition guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-transition-to-version-2.html#recommended-path-for-requiring-imdsv2) for more information.
2 changes: 2 additions & 0 deletions pkg/cloud/services/ec2/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ func (s *Service) CreateInstance(scope *scope.MachineScope, userData []byte, use
input.Tenancy = scope.AWSMachine.Spec.Tenancy

s.scope.Debug("Running instance", "machine-role", scope.Role())
s.scope.Debug("Running instance with instance metadata options", "metadata options", input.InstanceMetadataOptions)
out, err := s.runInstance(scope.Role(), input)
if err != nil {
// Only record the failure event if the error is not related to failed dependencies.
Expand Down Expand Up @@ -981,6 +982,7 @@ func (s *Service) ModifyInstanceMetadataOptions(instanceID string, options *infr
InstanceId: aws.String(instanceID),
}

s.scope.Info("Updating instance metadata options", "instance id", instanceID, "options", input)
if _, err := s.EC2Client.ModifyInstanceMetadataOptions(input); err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/suites/unmanaged/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,7 @@ func assertInstanceMetadataOptions(instanceID string, expected infrav1.InstanceM
metadataOptions := result.Reservations[0].Instances[0].MetadataOptions
Expect(metadataOptions).ToNot(BeNil())

Expect(metadataOptions.HttpTokens).To(HaveValue(Equal(string(expected.HTTPTokens)))) // IMDSv2 enabled
Expect(metadataOptions.HttpTokens).To(HaveValue(Equal(string(expected.HTTPTokens))))
Expect(metadataOptions.HttpEndpoint).To(HaveValue(Equal(string(expected.HTTPEndpoint))))
Expect(metadataOptions.InstanceMetadataTags).To(HaveValue(Equal(string(expected.InstanceMetadataTags))))
Expect(metadataOptions.HttpPutResponseHopLimit).To(HaveValue(Equal(expected.HTTPPutResponseHopLimit)))
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/suites/unmanaged/unmanaged_functional_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,10 @@ var _ = ginkgo.Context("[unmanaged] [functional]", func() {

mdName := clusterName + "-md01"
machineTempalte := makeAWSMachineTemplate(namespace.Name, mdName, e2eCtx.E2EConfig.GetVariable(shared.AwsNodeMachineType), nil)
// A test to set IMDSv2 explicitly
machineTempalte.Spec.Template.Spec.InstanceMetadataOptions = &infrav1.InstanceMetadataOptions{
HTTPEndpoint: infrav1.InstanceMetadataEndpointStateEnabled,
HTTPPutResponseHopLimit: 1,
HTTPPutResponseHopLimit: 2,
HTTPTokens: infrav1.HTTPTokensStateRequired, // IMDSv2
InstanceMetadataTags: infrav1.InstanceMetadataEndpointStateDisabled,
}
Expand Down

0 comments on commit b568361

Please sign in to comment.