Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configure EC2 instance metadata options #4037

Merged
merged 4 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/v1beta1/awscluster_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ func (src *AWSCluster) ConvertTo(dstRaw conversion.Hub) error {
restoreControlPlaneLoadBalancerStatus(&restored.Status.Network.APIServerELB, &dst.Status.Network.APIServerELB)

dst.Spec.S3Bucket = restored.Spec.S3Bucket
if restored.Status.Bastion != nil {
dst.Status.Bastion.InstanceMetadataOptions = restored.Status.Bastion.InstanceMetadataOptions
}

return nil
}
Expand Down
2 changes: 2 additions & 0 deletions api/v1beta1/awsmachine_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func (src *AWSMachine) ConvertTo(dstRaw conversion.Hub) error {
}

dst.Spec.Ignition = restored.Spec.Ignition
dst.Spec.InstanceMetadataOptions = restored.Spec.InstanceMetadataOptions

return nil
}
Expand Down Expand Up @@ -81,6 +82,7 @@ func (r *AWSMachineTemplate) ConvertTo(dstRaw conversion.Hub) error {

dst.Spec.Template.ObjectMeta = restored.Spec.Template.ObjectMeta
dst.Spec.Template.Spec.Ignition = restored.Spec.Template.Spec.Ignition
dst.Spec.Template.Spec.InstanceMetadataOptions = restored.Spec.Template.Spec.InstanceMetadataOptions

return nil
}
Expand Down
8 changes: 8 additions & 0 deletions api/v1beta1/conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ func Convert_v1beta2_NetworkStatus_To_v1beta1_NetworkStatus(in *v1beta2.NetworkS
return autoConvert_v1beta2_NetworkStatus_To_v1beta1_NetworkStatus(in, out, s)
}

func Convert_v1beta2_AWSMachineSpec_To_v1beta1_AWSMachineSpec(in *v1beta2.AWSMachineSpec, out *AWSMachineSpec, s conversion.Scope) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what I believe is missing with the conversion that @Skarlso mentioned is that the conversion currently discards the new fields when converting down to v1beta1, so a conversion down to v1beta1 and back to v1beta2 will result in data loss.

To fix this, the additional fields that are not present on v1beta1 but exist on v1beta2 are encoded as a value on an annotation, and extracted back out when converting from v1beta1 to v1beta2.

Here's an example from one of my earlier PR's where @Skarlso helped me previously with the same sort of conversion logic: https://github.com/kubernetes-sigs/cluster-api-provider-aws/pull/3757/files#r989941779 and "sigs.k8s.io/controller-runtime/pkg/conversion" contains a number of helper methods related to conversion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Cameron. Sorry, I have my hands full with trying to fix this frigging test infra. :D

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for the hint @cnmcavoy

return autoConvert_v1beta2_AWSMachineSpec_To_v1beta1_AWSMachineSpec(in, out, s)
}

func Convert_v1beta2_Instance_To_v1beta1_Instance(in *v1beta2.Instance, out *Instance, s conversion.Scope) error {
return autoConvert_v1beta2_Instance_To_v1beta1_Instance(in, out, s)
}

func Convert_v1beta1_ClassicELB_To_v1beta2_LoadBalancer(in *ClassicELB, out *v1beta2.LoadBalancer, s conversion.Scope) error {
out.Name = in.Name
out.DNSName = in.DNSName
Expand Down
52 changes: 30 additions & 22 deletions api/v1beta1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/v1beta2/awsmachine_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ type AWSMachineSpec struct {
// InstanceID is the EC2 instance ID for this machine.
InstanceID *string `json:"instanceID,omitempty"`

// InstanceMetadataOptions is the metadata options for the EC2 instance.
// +optional
InstanceMetadataOptions *InstanceMetadataOptions `json:"instanceMetadataOptions,omitempty"`

// AMI is the reference to the AMI from which to create the machine instance.
AMI AMIReference `json:"ami,omitempty"`

Expand Down
12 changes: 12 additions & 0 deletions api/v1beta2/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,15 @@ func SetDefaults_Labels(obj *metav1.ObjectMeta) { //nolint:golint,stylecheck
clusterv1.ClusterctlMoveHierarchyLabelName: ""}
}
}

// SetDefaults_AWSMachineSpec is used by defaulter-gen.
func SetDefaults_AWSMachineSpec(obj *AWSMachineSpec) { //nolint:golint,stylecheck
if obj.InstanceMetadataOptions == nil {
obj.InstanceMetadataOptions = &InstanceMetadataOptions{
HTTPEndpoint: InstanceMetadataEndpointStateEnabled,
HTTPPutResponseHopLimit: 1,
HTTPTokens: HTTPTokensStateRequired, // Defaults to IMDSv2
InstanceMetadataTags: InstanceMetadataEndpointStateDisabled,
}
}
}
77 changes: 77 additions & 0 deletions api/v1beta2/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,83 @@ type Instance struct {
// IDs of the instance's volumes
// +optional
VolumeIDs []string `json:"volumeIDs,omitempty"`

// InstanceMetadataOptions is the metadata options for the EC2 instance.
// +optional
InstanceMetadataOptions *InstanceMetadataOptions `json:"instanceMetadataOptions,omitempty"`
}

// InstanceMetadataState describes the state of InstanceMetadataOptions.HttpEndpoint and InstanceMetadataOptions.InstanceMetadataTags
type InstanceMetadataState string

const (
// InstanceMetadataEndpointStateDisabled represents the disabled state
InstanceMetadataEndpointStateDisabled = InstanceMetadataState("disabled")

// InstanceMetadataEndpointStateEnabled represents the enabled state
InstanceMetadataEndpointStateEnabled = InstanceMetadataState("enabled")
)

// HTTPTokensState describes the state of InstanceMetadataOptions.HTTPTokensState
type HTTPTokensState string

const (
// HTTPTokensStateOptional represents the optional state
HTTPTokensStateOptional = HTTPTokensState("optional")

// HTTPTokensStateRequired represents the required state (IMDSv2)
HTTPTokensStateRequired = HTTPTokensState("required")
)

// InstanceMetadataOptions describes metadata options for the EC2 instance.
type InstanceMetadataOptions struct {
// Enables or disables the HTTP metadata endpoint on your instances.
//
// If you specify a value of disabled, you cannot access your instance metadata.
//
// Default: enabled
//
// +kubebuilder:validation:Enum:=enabled;disabled
// +kubebuilder:default=enabled
HTTPEndpoint InstanceMetadataState `json:"httpEndpoint,omitempty"`

// The desired HTTP PUT response hop limit for instance metadata requests. The
// larger the number, the further instance metadata requests can travel.
//
// Default: 1
//
// +kubebuilder:validation:Minimum:=1
// +kubebuilder:validation:Maximum:=64
// +kubebuilder:default=1
HTTPPutResponseHopLimit int64 `json:"httpPutResponseHopLimit,omitempty"`

// The state of token usage for your instance metadata requests.
//
// If the state is optional, you can choose to retrieve instance metadata with
// or without a session token on your request. If you retrieve the IAM role
// credentials without a token, the version 1.0 role credentials are returned.
// If you retrieve the IAM role credentials using a valid session token, the
// version 2.0 role credentials are returned.
//
// If the state is required, 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.
//
// Default: required
// +kubebuilder:validation:Enum:=optional;required
// +kubebuilder:default=required
HTTPTokens HTTPTokensState `json:"httpTokens,omitempty"`

// Set to enabled to allow access to instance tags from the instance metadata.
// Set to disabled to turn off access to instance tags from the instance metadata.
// For more information, see Work with instance tags using the instance metadata
// (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"`
}

// Volume encapsulates the configuration options for the storage device.
Expand Down
25 changes: 25 additions & 0 deletions api/v1beta2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions api/v1beta2/zz_generated.defaults.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading