From 2bd1d04cd943bc987cf09c7d68bbfdce68baaa8e Mon Sep 17 00:00:00 2001 From: Justin Steele Date: Mon, 30 Jun 2025 12:05:31 -0400 Subject: [PATCH 1/6] feat: set default value for are_legacy_imds_endpoints_disabled to true --- CHANGELOG.md | 4 ++++ lib/kitchen/driver/oci/instance/compute.rb | 2 +- lib/kitchen/driver/oci_version.rb | 2 +- spec/spec_helper/compute_helper.rb | 4 +++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b872c2d..dbc4645 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # kitchen-oci CHANGELOG +# 2.0.0 +- feat: set default value for `are_legacy_imds_endpoints_disabled` to `true` + > BREAKING CHANGE: This overrides the default value to `true` in accordance with latest [OCI secuirty guidelines](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm) + # 1.28.0 - feat: add instance_options to compute instance type diff --git a/lib/kitchen/driver/oci/instance/compute.rb b/lib/kitchen/driver/oci/instance/compute.rb index 3e7339c..235266a 100644 --- a/lib/kitchen/driver/oci/instance/compute.rb +++ b/lib/kitchen/driver/oci/instance/compute.rb @@ -83,7 +83,7 @@ def instance_source_via_image # Adds the instance options property to the launch details. def instance_options - return if config[:instance_options].empty? + config[:instance_options].merge!(are_legacy_imds_endpoints_disabled: true) unless config[:instance_options].key?(:are_legacy_imds_endpoints_disabled) launch_details.instance_options = OCI::Core::Models::InstanceOptions.new(config[:instance_options]) end diff --git a/lib/kitchen/driver/oci_version.rb b/lib/kitchen/driver/oci_version.rb index fe47b77..aead3aa 100644 --- a/lib/kitchen/driver/oci_version.rb +++ b/lib/kitchen/driver/oci_version.rb @@ -22,6 +22,6 @@ module Driver # Version string for Oracle OCI Kitchen driver # # @author Stephen Pearson () - OCI_VERSION = "1.28.0" + OCI_VERSION = "2.0.0" end end diff --git a/spec/spec_helper/compute_helper.rb b/spec/spec_helper/compute_helper.rb index e5f27c2..989ebb3 100644 --- a/spec/spec_helper/compute_helper.rb +++ b/spec/spec_helper/compute_helper.rb @@ -23,7 +23,7 @@ include_context "oci" include_context "net" - let(:compute_driver_config) { base_driver_config.merge!({ capacity_reservation_id: capacity_reservation }) } + let(:compute_driver_config) { base_driver_config.merge!(capacity_reservation_id: capacity_reservation) } let(:instance_ocid) { "ocid1.instance.oc1.fake.aaaaaaaaaabcdefghijklmnopqrstuvwxyz12345" } let(:instance_metadata) do { @@ -58,6 +58,7 @@ is_management_disabled: false, are_all_plugins_disabled: false ) + l.instance_options = OCI::Core::Models::InstanceOptions.new(are_legacy_imds_endpoints_disabled: true) end end @@ -86,6 +87,7 @@ is_management_disabled: false, are_all_plugins_disabled: false ) + l.instance_options = OCI::Core::Models::InstanceOptions.new(are_legacy_imds_endpoints_disabled: true) end end From 798813a2ee5735707080633639a044a329386e5d Mon Sep 17 00:00:00 2001 From: Justin Steele Date: Mon, 30 Jun 2025 13:01:58 -0400 Subject: [PATCH 2/6] docs: update readme --- README.md | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 39835af..6b2de45 100644 --- a/README.md +++ b/README.md @@ -121,11 +121,10 @@ These settings are optional: - `volume_id`, If you wish to clone your volume from an existing volume set this to the source volume's ID. They must be in the same Availability Domain. - `nsg_ids`, The option to connect up to 5 Network Security Groups to compute instance. - `custom_metadata`, Add metadata to the compute instance request - - `instance_options`, A hash of optional mutable instance options. - Initially, the only option [supported in the Ruby SDK](https://docs.oracle.com/en-us/iaas/tools/ruby/latest/OCI/Core/Models/InstanceOptions.html) - is `are_legacy_imds_endpoints_disabled`. - Customers who have [migrated to IMDSv2](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm#upgrading-v2) - should set this to `true` + - `instance_options`, A hash of optional mutable instance options.\ + Available options [supported in the Ruby SDK](https://docs.oracle.com/en-us/iaas/tools/ruby/latest/OCI/Core/Models/InstanceOptions.html) + - `are_legacy_imds_endpoints_disabled`, Boolean (default: `true`)\ + > Customers who have not [migrated to IMDSv2](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm#upgrading-v2) will need to set this to `false`. [[more](#imdsv2)] - `all_plugins_disabled`, Whether Oracle Cloud Agent can run all the available plugins (default: `false`) - `management_disabled`, Whether Oracle Cloud Agent can run all the available management plugins (default: `false`) - `monitoring_disabled`, Whether Oracle Cloud Agent can gather performance metrics and monitor the instance using the monitoring plugins (default: `false`) @@ -407,6 +406,19 @@ driver: vpus_per_gb: 30 ``` +## IMDSv2 +In accordance with [OCI security guidelines](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm), the driver is disabling the IMDSv1 endpoint by default. This overrides the current default setting +in OCI and could cause issues with [unsupported images](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm#upgrading-v2__supported-images). In the event legacy IMDS support is required, +the option can be provided to the driver: + +```yml +--- +driver: + name: oci + instance_options: + are_legacy_imds_endpoints_disabled: false +``` + ## Windows Support When launching Oracle provided Windows images, it may be helpful to allow kitchen-oci to inject powershell to configure WinRM and to set a randomized password that does not need to be changed on first login. If the `setup_winrm` parameter is set to true then the following steps will happen: From 9dc0f38d5a80c39ef16642093c575c91c634ad4f Mon Sep 17 00:00:00 2001 From: Justin Steele Date: Tue, 1 Jul 2025 16:16:46 -0400 Subject: [PATCH 3/6] feat: move instance_options to post-launch to soften the impact of the breaking change --- lib/kitchen/driver/oci/instance/compute.rb | 7 ------- lib/kitchen/driver/oci/mixin/actions.rb | 21 +++++++++++++++++++++ spec/spec_helper/compute_helper.rb | 8 ++++++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lib/kitchen/driver/oci/instance/compute.rb b/lib/kitchen/driver/oci/instance/compute.rb index 235266a..47ac1c0 100644 --- a/lib/kitchen/driver/oci/instance/compute.rb +++ b/lib/kitchen/driver/oci/instance/compute.rb @@ -81,13 +81,6 @@ def instance_source_via_image ) end - # Adds the instance options property to the launch details. - def instance_options - config[:instance_options].merge!(are_legacy_imds_endpoints_disabled: true) unless config[:instance_options].key?(:are_legacy_imds_endpoints_disabled) - - launch_details.instance_options = OCI::Core::Models::InstanceOptions.new(config[:instance_options]) - end - # Adds the source_details property to the launch_details for an instance that is being created from a boot volume. def instance_source_via_boot_volume return unless config[:boot_volume_id] diff --git a/lib/kitchen/driver/oci/mixin/actions.rb b/lib/kitchen/driver/oci/mixin/actions.rb index 7ea22f0..9bd2c8b 100644 --- a/lib/kitchen/driver/oci/mixin/actions.rb +++ b/lib/kitchen/driver/oci/mixin/actions.rb @@ -33,6 +33,7 @@ def launch(state, inst) state_details = inst.launch state.merge!(state_details) instance.transport.connection(state).wait_until_ready + instance_options(state, inst) if config[:instance_type] == "compute" end # Executes the post script on the instance. @@ -68,6 +69,26 @@ def execute_post_create_file(state) end end + # Applies instance options. + # + # @param state [Hash] (see Kitchen::StateFile) + # @param inst [Class] the specific class of instance being rebooted. + def instance_options(state, inst) + return unless instance_options? + + inst.logger.info("Applying the following instance options:") + config[:instance_options].each { |o, v| inst.logger.info("- #{o}: #{v}") } + inst.api.compute.update_instance(state[:server_id], OCI::Core::Models::UpdateInstanceDetails.new(instance_options: OCI::Core::Models::InstanceOptions.new(config[:instance_options]))) + end + + # Attempts to disable IMDSv1 even if not explicitly specified in the config. This is in line with current security guidance from OCI. + # Acts as a guard for setting instance options. + def instance_options? + config[:instance_options].merge!(are_legacy_imds_endpoints_disabled: true) unless config[:instance_options].key?(:are_legacy_imds_endpoints_disabled) + # Basically tell me if there's more stuff in there than `are_legacy_imds_endpoints_disabled: false`. If so, then proceed to setting it. + config[:instance_options].reject { |o, v| o == :are_legacy_imds_endpoints_disabled && !v }.any? + end + # Reboots an instance. # # @param state [Hash] (see Kitchen::StateFile) diff --git a/spec/spec_helper/compute_helper.rb b/spec/spec_helper/compute_helper.rb index 989ebb3..0678bd5 100644 --- a/spec/spec_helper/compute_helper.rb +++ b/spec/spec_helper/compute_helper.rb @@ -25,6 +25,11 @@ let(:compute_driver_config) { base_driver_config.merge!(capacity_reservation_id: capacity_reservation) } let(:instance_ocid) { "ocid1.instance.oc1.fake.aaaaaaaaaabcdefghijklmnopqrstuvwxyz12345" } + let(:instance_options) { + OCI::Core::Models::UpdateInstanceDetails.new( + instance_options: OCI::Core::Models::InstanceOptions.new(are_legacy_imds_endpoints_disabled: true) + ) + } let(:instance_metadata) do { "ssh_authorized_keys" => ssh_pub_key, @@ -58,7 +63,6 @@ is_management_disabled: false, are_all_plugins_disabled: false ) - l.instance_options = OCI::Core::Models::InstanceOptions.new(are_legacy_imds_endpoints_disabled: true) end end @@ -87,7 +91,6 @@ is_management_disabled: false, are_all_plugins_disabled: false ) - l.instance_options = OCI::Core::Models::InstanceOptions.new(are_legacy_imds_endpoints_disabled: true) end end @@ -113,5 +116,6 @@ allow(compute_client).to receive(:get_volume_attachment).with(pv_attachment_ocid).and_return(pv_attachment_response) allow(compute_client).to receive(:detach_volume).with(iscsi_attachment_ocid).and_return(nil_response) allow(compute_client).to receive(:detach_volume).with(pv_attachment_ocid).and_return(nil_response) + allow(compute_client).to receive(:update_instance).with(instance_ocid, instance_options).and_return(nil_response) end end From 7acb9476da3610dd7481e429674b7821866071a3 Mon Sep 17 00:00:00 2001 From: Justin Steele Date: Wed, 2 Jul 2025 09:17:03 -0400 Subject: [PATCH 4/6] feat: add post launch check for legacy metadata endpoints being enabled --- lib/kitchen/driver/oci/mixin/actions.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/kitchen/driver/oci/mixin/actions.rb b/lib/kitchen/driver/oci/mixin/actions.rb index 9bd2c8b..1d8498f 100644 --- a/lib/kitchen/driver/oci/mixin/actions.rb +++ b/lib/kitchen/driver/oci/mixin/actions.rb @@ -33,7 +33,8 @@ def launch(state, inst) state_details = inst.launch state.merge!(state_details) instance.transport.connection(state).wait_until_ready - instance_options(state, inst) if config[:instance_type] == "compute" + instance_options(state, inst) + are_legacy_imds_endpoints_disbled?(state, inst) end # Executes the post script on the instance. @@ -84,11 +85,21 @@ def instance_options(state, inst) # Attempts to disable IMDSv1 even if not explicitly specified in the config. This is in line with current security guidance from OCI. # Acts as a guard for setting instance options. def instance_options? + return false unless config[:instance_type] == "compute" + config[:instance_options].merge!(are_legacy_imds_endpoints_disabled: true) unless config[:instance_options].key?(:are_legacy_imds_endpoints_disabled) # Basically tell me if there's more stuff in there than `are_legacy_imds_endpoints_disabled: false`. If so, then proceed to setting it. config[:instance_options].reject { |o, v| o == :are_legacy_imds_endpoints_disabled && !v }.any? end + # Checks if legacy metadata is disabled. + def are_legacy_imds_endpoints_disbled?(state, inst) + return unless config[:instance_type] == "compute" + + imds = inst.api.compute.get_instance(state[:server_id]).data.instance_options.are_legacy_imds_endpoints_disabled + inst.logger.warn("Legacy IMDSv1 endpoint is enabled.") unless imds + end + # Reboots an instance. # # @param state [Hash] (see Kitchen::StateFile) From 829ce170fcbee19cda35c72f3e5c304d669ea6db Mon Sep 17 00:00:00 2001 From: Justin Steele Date: Wed, 2 Jul 2025 09:21:16 -0400 Subject: [PATCH 5/6] fix: add instance_options to stubbed compute_response --- spec/spec_helper/create_helper.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/spec_helper/create_helper.rb b/spec/spec_helper/create_helper.rb index 0103c06..f71a2af 100644 --- a/spec/spec_helper/create_helper.rb +++ b/spec/spec_helper/create_helper.rb @@ -21,7 +21,8 @@ let(:compute_response) do OCI::Response.new(200, nil, OCI::Core::Models::Instance.new(id: instance_ocid, image_id: image_ocid, - lifecycle_state: Lifecycle.compute("running"))) + lifecycle_state: Lifecycle.compute("running"), + instance_options: OCI::Core::Models::InstanceOptions.new(are_legacy_imds_endpoints_disabled: true))) end let(:dbaas_response) do OCI::Response.new(200, nil, OCI::Database::Models::DbSystem.new(id: db_system_ocid, lifecycle_state: Lifecycle.dbaas("available"))) From a502cb2707e0905917b9d46939166bf5069d0ff7 Mon Sep 17 00:00:00 2001 From: Justin Steele Date: Mon, 14 Jul 2025 08:58:42 -0400 Subject: [PATCH 6/6] fix: typo in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b2de45..6db6e1a 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ These settings are optional: - `custom_metadata`, Add metadata to the compute instance request - `instance_options`, A hash of optional mutable instance options.\ Available options [supported in the Ruby SDK](https://docs.oracle.com/en-us/iaas/tools/ruby/latest/OCI/Core/Models/InstanceOptions.html) - - `are_legacy_imds_endpoints_disabled`, Boolean (default: `true`)\ + - `are_legacy_imds_endpoints_disabled`, Boolean (default: `true`) > Customers who have not [migrated to IMDSv2](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm#upgrading-v2) will need to set this to `false`. [[more](#imdsv2)] - `all_plugins_disabled`, Whether Oracle Cloud Agent can run all the available plugins (default: `false`) - `management_disabled`, Whether Oracle Cloud Agent can run all the available management plugins (default: `false`)