* to the *source* attribute value, as in:
+```
+ source = "github.com/oracle-quickstart/terraform-oci-secure-workloads//cis-compute-storage?ref=v0.1.0"
+```
+
## Module Functioning
-The module defines two top level attributes used to manage instances and storage:
+The module defines two top level variables used to manage instances, storage, clusters and cluster configurations:
- **instances_configuration** – for managing Compute instances.
- **storage_configuration** – for managing storage, including Block Volumes and File System Storage.
+- **clusters_configuration** – for managing clusters, including cluster networks and compute clusters.
+- **cluster_instances_configuration** – for managing instance configurations used in cluster networks.
### Aspects Driven by CIS Profile Levels
@@ -123,7 +163,7 @@ The CIS Benchmark profile levels drive some aspects of Compute and Storage. In t
### Compute
-Compute instances are managed using the **instances_configuration** object. It contains a set of attributes starting with the prefix **default_** and one attribute named **instances**. The **default_** attribute values are applied to all instances within **instances**, unless overridden at the instance level.
+Compute instances are managed using the **instances_configuration** variable. It contains a set of attributes starting with the prefix **default_** and one attribute named **instances**. The **default_** attribute values are applied to all instances within **instances**, unless overridden at the instance level.
The *default_* attributes are the following:
- **default_compartment_id** – Default compartment for all instances. It can be overridden by *compartment_id* attribute in each instance. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
@@ -133,6 +173,8 @@ The *default_* attributes are the following:
- **default_cis_level** – (Optional) Default CIS OCI Benchmark profile level for all instances. Level "2" enforces usage of customer managed keys for boot volume encryption. Default is "1". It can be overridden by *cis_level* attribute in each instance.
- **default_defined_tags** – (Optional) Default defined tags for all instances. It can be overridden by *defined_tags* attribute in each instance.
- **default_freeform_tags** – (Optional) Default freeform tags for all instances. It can be overridden by *freeform_tags* attribute in each instance.
+- **default_cloud_init_heredoc_script** – (Optional) Default cloud-init script in [Terraform heredoc style](https://developer.hashicorp.com/terraform/language/expressions/strings#heredoc-strings) that is applied to all instances. It has precedence over *default_cloud_init_script_file*. Use this when the script cannot be made available in the file system. **Any further changes to the script triggers instance recreation on subsequent plan/apply.**
+- **default_cloud_init_script_file** – (Optional) Default cloud-init script file that is applied to all instances. Use this when the script is available in the file system. **Any further changes to the script triggers instance recreation on subsequent plan/apply.**
The instances themselves are defined within the **instances** attribute, In Terraform terms, it is a map of objects. where each object is referred by an identifying key. The supported attributes are listed below. For better usability, most attributes are grouped in logical blocks. They are properly indented in the list.
- **compartment_id** – (Optional) The instance compartment. *default_compartment_id* is used if undefined. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
@@ -140,6 +182,7 @@ The instances themselves are defined within the **instances** attribute, In Terr
- **shape** – The instance shape. See [Compute Shapes](https://docs.oracle.com/en-us/iaas/Content/Compute/References/computeshapes.htm) for OCI Compute shapes.
- **name** – The instance name.
- **platform_type** – (Optional) The platform type. Assigning this attribute enables important platform security features in the Compute service. See [Enabling Platform Features](#platform-features) for more information. Valid values are "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM". By default, no platform features are enabled.
+- **cluster_id** – (Optional) The Compute cluster the instance is added to. It can take either a literal cluster OCID or cluster key defined in the *clusters_configuration* variable.
- **ssh_public_key_path** – (Optional) The SSH public key path used to access the instance. *default_ssh_public_key_path* is used if undefined.
- **defined_tags** – (Optional) The instance defined tags. *default_defined_tags* is used if undefined.
- **freeform_tags** – (Optional) The instance freeform tags. *default_freeform_tags* is used if undefined.
@@ -203,6 +246,9 @@ The instances themselves are defined within the **instances** attribute, In Terr
- **plugins** – (Optional) The list of plugins to manage. Each plugin has a name and a boolean flag that enables it.
- **name** – The plugin name. **It must be a valid plugin name**. The plugin names are available in [Oracle Cloud Agent documentation](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm) and in [compute-only example](./examples/compute-only/input.auto.tfvars.template) as well.
- **enabled** – Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
+- **cloud_init** – (Optional) a script that is automatically executed once the instance starts out. Use either *heredoc_script* (when the script cannot be made available in the file system) or *script_file* (when the script is available in the file system). **Any further changes to the script (supplied in either way) triggers instance recreation on subsequent plan/apply.**
+ - **heredoc_script** – (Optional) cloud-init script in [Terraform heredoc style](https://developer.hashicorp.com/terraform/language/expressions/strings#heredoc-strings) that is applied to the instance. It has precedence over *script_file*.
+ - **script_file** – (Optional) cloud-init script file that is applied to the instance.
#### Cloud Agent Requirements
##### IAM Policy Requirements
@@ -281,7 +327,7 @@ Additionally, in-transit encryption is only available to paravirtualized volumes
### Storage
-Storage is managed using the **storage_configuration** object. It contains a set of attributes starting with the prefix **default_** and two attribute named **block_volumes** and **file_storage**. The **default_** attribute values are applied to all storage units within **block_volumes** and **file_storage**, unless overridden at the storage unit level.
+Storage is managed using the **storage_configuration** variable. It contains a set of attributes starting with the prefix **default_** and two attribute named **block_volumes** and **file_storage**. The **default_** attribute values are applied to all storage units within **block_volumes** and **file_storage**, unless overridden at the storage unit level.
The defined **default_** attributes are the following:
- **default_compartment_id** – (Optional) The default compartment for all storage units. It can be overridden by *compartment_id* attribute in each unit. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
@@ -564,6 +610,63 @@ Snapshot policies are defined using the optional attribute **snapshot_policies**
As mentioned, default snapshot policies are created for file systems that do not have a snapshot policy. The default snapshot policies are defined with a single schedule, set to run weekly at 23:00 UTC on sundays.
+
+#### Clusters
+
+The module can manage cluster networks and compute clusters.
+
+A [cluster network](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/managingclusternetworks.htm) is a pool of high performance computing (HPC) instances that are connected with a high-bandwidth, ultra low-latency network. They're designed for highly demanding parallel computing jobs.
+
+A [Compute cluster](https://docs.oracle.com/iaas/Content/Compute/Tasks/compute-clusters.htm) is a remote direct memory access (RDMA) network group. You can create high performance computing (HPC) instances in the network and manage them individually.
+
+Clusters are managed using the **clusters_configuration** variable. It contains a set of attributes starting with the prefix **default_** and one attribute named **clusters**. The **default_** attribute values are applied to all clusters within **clusters**, unless overridden at the cluster level.
+
+The *default_* attributes are the following:
+- **default_compartment_id** – Default compartment for all clusters. It can be overridden by *compartment_id* attribute in each cluster. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_defined_tags** – (Optional) Default defined tags for all clusters. It can be overridden by *defined_tags* attribute in each cluster.
+- **default_freeform_tags** – (Optional) Default freeform tags for all clusters. It can be overridden by *freeform_tags* attribute in each cluster.
+
+The clusters themselves are defined within the **clusters** attribute, In Terraform terms, it is a map of objects. where each object is referred by an identifying key. The supported attributes are listed below. For better usability, most attributes are grouped in logical blocks. They are properly indented in the list.
+
+- **compartment_id** – (Optional) The cluster compartment. *default_compartment_id* is used if undefined. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **type** – (Optional) The cluster type. Valid values: "cluster_network", "compute_cluster". Default is "cluster_network".
+- **availability_domain** – (Optional) The availability domain for cluster instances. Default is 1.
+- **name** – The cluster display name.
+- **defined_tags** – (Optional) The cluster defined_tags. *default_defined_tags* is used if undefined.
+- **freeform_tags** – (Optional) The cluster freeform_tags. *default_freeform_tags* is used if undefined.
+- **cluster_network_settings** – (Optional) Cluster network settings. **Only applicable if type is "cluster_network"**.
+ - **instance_configuration_id** – The instance configuration id to use in this cluster. It can be a literal OCID or a configuration key defined in *cluster_instances_configuration* variable.
+ - **instance_pool** – (Optional) Cluster instance pool settings.
+ - **name** – (Optional) The instance pool name.
+ - **size** – (Optional) The number of instances in the instance pool. Default is 1.
+ - **networking** – Networking settings.
+ - **subnet_id** – The subnet where instances primary VNIC is placed.
+ - **ipv6_enable** – (Optional) Whether IPv6 is enabled for instances primary VNIC. Default is false.
+ - **ipv6_subnet_cidrs** = – (Optional) A list of IPv6 subnet CIDR ranges from which the primary VNIC is assigned an IPv6 address. Only applicable if ipv6_enable for primary VNIC is true. Default is [].
+ - **secondary_vnic_settings** – (Optional) Secondary VNIC settings
+ - **subnet_id** – The subnet where instances secondary VNIC are created.
+ - **name** – (Optional) The secondary VNIC name.
+ - **ipv6_enable** – (Optional) Whether IPv6 is enabled for the secondary VNIC. Default is false.
+ - **ipv6_subnet_cidrs** – (Optional) A list of IPv6 subnet CIDR ranges from which the secondary VNIC is assigned an IPv6 address. Only applicable if ipv6_enable for secondary VNIC is true. Default is [].
+
+Cluster instance configurations required by cluster networks are managed using the **cluster_instances_configuration** variable. It contains a set of attributes starting with the prefix **default_** and one attribute named **configurations**. The **default_** attribute values are applied to all instance configurations within **configurations**, unless overridden at the configuration level.
+
+The *default_* attributes are the following:
+- **default_compartment_id** – Default compartment for all configurations. It can be overridden by *compartment_id* attribute in each configurations. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_defined_tags** – (Optional) Default defined tags for all configurations. It can be overridden by *defined_tags* attribute in each configuration.
+- **default_freeform_tags** – (Optional) Default freeform tags for all configurations. It can be overridden by *freeform_tags* attribute in each configuration.
+
+The configurations themselves are defined within the **configurations** attribute, In Terraform terms, it is a map of objects. where each object is referred by an identifying key. The supported attributes are listed below.
+
+- **compartment_id** – (Optional) The compartment where the instance configuration is created. *default_compartment_id* is used if undefined.
+- **name** – (Optional) The instance configuration display name.
+- **instance_type** – (Optional) the instance type. Default is "compute".
+- **template_instance_id** – The existing instance id to use as the configuration template for all instances in the cluster instance pool. It can be a literal instance OCID, an instance key defined in the *instances_configuration* variable, or an instance key defined in the *instances_dependency* variable.
+ **NOTE: The instance must have a shape that supports cluster networks**.
+- **defined_tags** – (Optional) The instance configuration defined_tags. *default_defined_tags* is used if undefined.
+- **freeform_tags** – (Optional) The instance configuration freeform_tags. *default_freeform_tags* is used if undefined.
+
+
### External Dependencies
An optional feature, external dependencies are resources managed elsewhere that resources managed by this module depends on. The following dependencies are supported:
diff --git a/cis-compute-storage/SPEC.md b/cis-compute-storage/SPEC.md
index 27318df..6f19183 100644
--- a/cis-compute-storage/SPEC.md
+++ b/cis-compute-storage/SPEC.md
@@ -8,6 +8,7 @@ No requirements.
|------|---------|
| [oci](#provider\_oci) | n/a |
| [oci.block\_volumes\_replication\_region](#provider\_oci.block\_volumes\_replication\_region) | n/a |
+| [template](#provider\_template) | n/a |
## Modules
@@ -43,6 +44,7 @@ No modules.
| [oci_identity_availability_domains.fs_ads](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_availability_domains) | data source |
| [oci_identity_availability_domains.mt_ads](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_availability_domains) | data source |
| [oci_identity_availability_domains.snapshot_ads](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_availability_domains) | data source |
+| [template_file.cloud_config](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) | data source |
## Inputs
@@ -51,7 +53,7 @@ No modules.
| [compartments\_dependency](#input\_compartments\_dependency) | A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the compartment OCID) of string type. | `map(any)` | `null` | no |
| [enable\_output](#input\_enable\_output) | Whether Terraform should enable the module output. | `bool` | `true` | no |
| [file\_system\_dependency](#input\_file\_system\_dependency) | A map of objects containing the externally managed file storage resources this module may depend on. This is used when setting file system replication using target file systems managed in another Terraform configuration. All map objects must have the same type and must contain at least an 'id' attribute (representing the file system OCID) of string type. | `map(any)` | `null` | no |
-| [instances\_configuration](#input\_instances\_configuration) | Compute instances configuration attributes. | object({
default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
instances = map(object({ # the instances to manage in this configuration.
cis_level = optional(string)
compartment_id = optional(string) # the compartment where the instance is created. default_compartment_ocid is used if this is not defined.
shape = string # the instance shape.
name = string # the instance display name.
platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
image = object({ # the base image. You must provider either the id or (name and publisher name).
id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
name = optional(string) # the image name to search for in marketplace.
publisher_name = optional(string) # the publisher name of the image name.
})
placement = optional(object({ # placement settings
availability_domain = optional(number,1) # the instance availability domain. Default is 1.
fault_domain = optional(number,1) # the instance fault domain. Default is 1.
}))
boot_volume = optional(object({ # boot volume settings
type = optional(string,"paravirtualized") # boot volume emulation type. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio".
firmware = optional(string) # firmware used to boot the VM. Valid options: "BIOS" (compatible with both 32 bit and 64 bit operating systems that boot using MBR style bootloaders), "UEFI_64" (default for platform images).
size = optional(number,50) # boot volume size. Default is 50GB (minimum allowed by OCI).
preserve_on_instance_deletion = optional(bool,true) # whether to preserve boot volume after deletion. Default is true.
secure_boot = optional(bool, false) # prevents unauthorized boot loaders and operating systems from booting.
measured_boot = optional(bool, false) # enhances boot security by taking and storing measurements of boot components, such as bootloaders, drivers, and operating systems. Bare metal instances do not support Measured Boot.
trusted_platform_module = optional(bool, false) # used to securely store boot measurements.
backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
}))
volumes_emulation_type = optional(string,"paravirtualized") # Emulation type for attached storage volumes. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio". Module supported values for automated attachment: "paravirtualized", "iscsi".
networking = optional(object({ # networking settings
type = optional(string,"paravirtualized") # emulation type for the physical network interface card (NIC). Valid values: "paravirtualized" (default), "e1000", "vfio".
private_ip = optional(string) # a private IP address of your choice to assign to the primary VNIC.
hostname = optional(string) # the primary VNIC hostname.
assign_public_ip = optional(bool) # whether to assign the primary VNIC a public IP. Defaults to whether the subnet is public or private.
subnet_id = optional(string) # the subnet where the primary VNIC is created. default_subnet_id is used if this is not defined.
network_security_groups = optional(list(string)) # list of network security groups the primary VNIC should be placed into.
skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the primary VNIC. Default is false.
secondary_ips = optional(map(object({ # list of secondary private IP addresses for the primary VNIC.
display_name = optional(string) # Secondary IP display name.
hostname = optional(string) # Secondary IP host name.
private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
})))
secondary_vnics = optional(map(object({
display_name = optional(string) # the VNIC display name.
private_ip = optional(string) # a private IP address of your choice to assign to the VNIC.
hostname = optional(string) # the VNIC hostname.
assign_public_ip = optional(bool) # whether to assign the VNIC a public IP. Defaults to whether the subnet is public or private.
subnet_id = optional(string) # the subnet where the VNIC is created. default_subnet_id is used if this is not defined.
network_security_groups = optional(list(string)) # list of network security groups the VNIC should be placed into.
skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the VNIC. Default is false.
nic_index = optional(number,0) # the physical network interface card (NIC) the VNIC will use. Defaults to 0. Certain bare metal instance shapes have two active physical NICs (0 and 1).
secondary_ips = optional(map(object({ # list of secondary private IP addresses for the VNIC.
display_name = optional(string) # Secondary IP display name.
hostname = optional(string) # Secondary IP host name.
private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
})))
defined_tags = optional(map(string)) # VNIC defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # VNIC freeform_tags. default_freeform_tags is used if this is not defined.
})))
}))
encryption = optional(object({ # encryption settings
kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
encrypt_in_transit_on_instance_create = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance creation time only.
encrypt_in_transit_on_instance_update = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance update time only.
encrypt_data_in_use = optional(bool, false) # whether the instance encrypts data in-use (in memory) while being processed. A.k.a confidential computing.
}))
flex_shape_settings = optional(object({ # flex shape settings
memory = optional(number,16) # the instance memory for Flex shapes. Default is 16GB.
ocpus = optional(number,1) # the instance ocpus number for Flex shapes. Default is 1.
}))
cloud_agent = optional(object({ # Cloud Agent settings
disable_management = optional(bool,false) # whether the management plugins should be disabled. These plugins are enabled by default in the Compute service.
disable_monitoring = optional(bool,false) # whether the monitoring plugins should be disabled. These plugins are enabled by default in the Compute service.
plugins = optional(list(object({ # list of plugins
name = string # the plugin name. It must be a valid plugin name. The plugin names are available in https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm and in compute-only example(./examples/compute-only/input.auto.tfvars.template) as well.
enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
})))
}))
ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
}))
})
| `null` | no |
+| [instances\_configuration](#input\_instances\_configuration) | Compute instances configuration attributes. | object({
default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
default_cloud_init_heredoc_script = optional(string), # a cloud-init script in Terraform heredoc style that is applied to all instances. It has precedence over default_cloud_init_script_file.
default_cloud_init_script_file = optional(string), # a cloud-init script file that is applied to all instances.
instances = map(object({ # the instances to manage in this configuration.
cis_level = optional(string)
compartment_id = optional(string) # the compartment where the instance is created. default_compartment_ocid is used if this is not defined.
shape = string # the instance shape.
name = string # the instance display name.
platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
image = object({ # the base image. You must provider either the id or (name and publisher name).
id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
name = optional(string) # the image name to search for in marketplace.
publisher_name = optional(string) # the publisher name of the image name.
})
placement = optional(object({ # placement settings
availability_domain = optional(number,1) # the instance availability domain. Default is 1.
fault_domain = optional(number,1) # the instance fault domain. Default is 1.
}))
boot_volume = optional(object({ # boot volume settings
type = optional(string,"paravirtualized") # boot volume emulation type. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio".
firmware = optional(string) # firmware used to boot the VM. Valid options: "BIOS" (compatible with both 32 bit and 64 bit operating systems that boot using MBR style bootloaders), "UEFI_64" (default for platform images).
size = optional(number,50) # boot volume size. Default is 50GB (minimum allowed by OCI).
preserve_on_instance_deletion = optional(bool,true) # whether to preserve boot volume after deletion. Default is true.
secure_boot = optional(bool, false) # prevents unauthorized boot loaders and operating systems from booting.
measured_boot = optional(bool, false) # enhances boot security by taking and storing measurements of boot components, such as bootloaders, drivers, and operating systems. Bare metal instances do not support Measured Boot.
trusted_platform_module = optional(bool, false) # used to securely store boot measurements.
backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
}))
volumes_emulation_type = optional(string,"paravirtualized") # Emulation type for attached storage volumes. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio". Module supported values for automated attachment: "paravirtualized", "iscsi".
networking = optional(object({ # networking settings
type = optional(string,"paravirtualized") # emulation type for the physical network interface card (NIC). Valid values: "paravirtualized" (default), "e1000", "vfio".
private_ip = optional(string) # a private IP address of your choice to assign to the primary VNIC.
hostname = optional(string) # the primary VNIC hostname.
assign_public_ip = optional(bool) # whether to assign the primary VNIC a public IP. Defaults to whether the subnet is public or private.
subnet_id = optional(string) # the subnet where the primary VNIC is created. default_subnet_id is used if this is not defined.
network_security_groups = optional(list(string)) # list of network security groups the primary VNIC should be placed into.
skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the primary VNIC. Default is false.
secondary_ips = optional(map(object({ # list of secondary private IP addresses for the primary VNIC.
display_name = optional(string) # Secondary IP display name.
hostname = optional(string) # Secondary IP host name.
private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
})))
secondary_vnics = optional(map(object({
display_name = optional(string) # the VNIC display name.
private_ip = optional(string) # a private IP address of your choice to assign to the VNIC.
hostname = optional(string) # the VNIC hostname.
assign_public_ip = optional(bool) # whether to assign the VNIC a public IP. Defaults to whether the subnet is public or private.
subnet_id = optional(string) # the subnet where the VNIC is created. default_subnet_id is used if this is not defined.
network_security_groups = optional(list(string)) # list of network security groups the VNIC should be placed into.
skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the VNIC. Default is false.
nic_index = optional(number,0) # the physical network interface card (NIC) the VNIC will use. Defaults to 0. Certain bare metal instance shapes have two active physical NICs (0 and 1).
secondary_ips = optional(map(object({ # list of secondary private IP addresses for the VNIC.
display_name = optional(string) # Secondary IP display name.
hostname = optional(string) # Secondary IP host name.
private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
})))
defined_tags = optional(map(string)) # VNIC defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # VNIC freeform_tags. default_freeform_tags is used if this is not defined.
})))
}))
encryption = optional(object({ # encryption settings
kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
encrypt_in_transit_on_instance_create = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance creation time only.
encrypt_in_transit_on_instance_update = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance update time only.
encrypt_data_in_use = optional(bool, false) # whether the instance encrypts data in-use (in memory) while being processed. A.k.a confidential computing.
}))
flex_shape_settings = optional(object({ # flex shape settings
memory = optional(number,16) # the instance memory for Flex shapes. Default is 16GB.
ocpus = optional(number,1) # the instance ocpus number for Flex shapes. Default is 1.
}))
cloud_agent = optional(object({ # Cloud Agent settings
disable_management = optional(bool,false) # whether the management plugins should be disabled. These plugins are enabled by default in the Compute service.
disable_monitoring = optional(bool,false) # whether the monitoring plugins should be disabled. These plugins are enabled by default in the Compute service.
plugins = optional(list(object({ # list of plugins
name = string # the plugin name. It must be a valid plugin name. The plugin names are available in https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm and in compute-only example(./examples/compute-only/input.auto.tfvars.template) as well.
enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
})))
}))
cloud_init = optional(object({
heredoc_script = optional(string) # a cloud-init script in Terraform heredoc style that is applied to the instance. It has precedence over script_file.
script_file = optional(string) # a cloud-init script file that is applied to the instance.
}))
ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
}))
})
| `null` | no |
| [instances\_dependency](#input\_instances\_dependency) | A map of objects containing the externally managed Compute instances this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the instance OCID) of string type. | `map(any)` | `null` | no |
| [kms\_dependency](#input\_kms\_dependency) | A map of objects containing the externally managed encryption keys this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the key OCID) of string type. | `map(any)` | `null` | no |
| [module\_name](#input\_module\_name) | The module name. | `string` | `"cis-compute-storage"` | no |
@@ -67,3 +69,5 @@ No modules.
| [file\_systems\_mount\_targets](#output\_file\_systems\_mount\_targets) | n/a |
| [file\_systems\_snapshot\_policies](#output\_file\_systems\_snapshot\_policies) | n/a |
| [instances](#output\_instances) | The Compute instances |
+| [private\_ips](#output\_private\_ips) | The private IPs |
+| [vnic\_attachments](#output\_vnic\_attachments) | The VNIC attachments |
diff --git a/cis-compute-storage/cluster_instances_configuration.tf b/cis-compute-storage/cluster_instances_configuration.tf
new file mode 100644
index 0000000..1e96e1d
--- /dev/null
+++ b/cis-compute-storage/cluster_instances_configuration.tf
@@ -0,0 +1,455 @@
+# locals {
+# supported_shapes = {
+# (lower("BM.HPC2.36")) : "BM.HPC2.36"
+# (lower("BM.GPU.A100-v2.8")) : "BM.GPU.A100-v2.8"
+# (lower("BM.GPU4.8")) : "BM.GPU4.8"
+# (lower("BM.Optimized3.36")) : "BM.Optimized3.36"
+# }
+# }
+
+data "oci_core_instance" "these" {
+ for_each = var.cluster_instances_configuration != null ? (var.cluster_instances_configuration.configurations != null ? ({for k, v in var.cluster_instances_configuration.configurations : k => v if v.template_instance_id != null}): {}) : {}
+ instance_id = contains(keys(oci_core_instance.these),each.value.template_instance_id) ? oci_core_instance.these[each.value.template_instance_id].id : length(regexall("^ocid1.*$", each.value.template_instance_id)) > 0 ? each.value.template_instance_id : var.instances_dependency[each.value.template_instance_id].id
+}
+
+resource "oci_core_instance_configuration" "these" {
+ for_each = var.cluster_instances_configuration != null ? (var.cluster_instances_configuration.configurations != null ? var.cluster_instances_configuration.configurations : {}) : {}
+# lifecycle {
+# ## Check 1: supported shapes check for NEW instances
+# precondition {
+# condition = each.value.instance_details != null ? (contains(keys(local.supported_shapes),lower(coalesce(each.value.instance_details.shape,"BM.Optimized3.36")))) : true
+# error_message = "VALIDATION FAILURE in instance configuration \"${each.key}\": invalid \"${each.value.instance_details != null ? lower(coalesce(each.value.instance_details.shape,"BM.Optimized3.36")) : ""}\" instance shape. Supported instance shape values for cluster networks are ${join(", ",[for v in values(local.supported_shapes): "\"${v}\""])}, case insensitive."
+# }
+# ## Check 1: supported shapes check for EXISTING instances
+# precondition {
+# condition = each.value.template_instance_id != null ? (contains(keys(local.supported_shapes),lower(data.oci_core_instance.these[each.key].shape))) : true
+# #error_message = "VALIDATION FAILURE in instance configuration \"${each.key}\": the instance shape of provided \"template_instance_id\" attribute (\"${coalesce(each.value.template_instance_id,"__void__")}\") is invalid: \"${contains(keys(local.supported_shapes),lower(data.oci_core_instance.these[each.key].shape)) ? data.oci_core_instance.these[each.key].shape : ""}\". Supported instance shape values for cluster networks are ${join(", ",[for v in values(local.supported_shapes): "\"${v}\""])}."
+# error_message = "VALIDATION FAILURE in instance configuration \"${each.key}\": the instance shape of provided \"template_instance_id\" attribute (\"${coalesce(each.value.template_instance_id,"__void__")}\") is invalid. Supported instance shape values for cluster networks are ${join(", ",[for v in values(local.supported_shapes): "\"${v}\""])}."
+# }
+# }
+ #Required
+ compartment_id = each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (length(regexall("^ocid1.*$", var.cluster_instances_configuration.default_compartment_id)) > 0 ? var.cluster_instances_configuration.default_compartment_id : var.compartments_dependency[var.cluster_instances_configuration.default_compartment_id].id)
+
+ #Optional
+ display_name = each.value.name
+ defined_tags = each.value.defined_tags != null ? each.value.defined_tags : var.cluster_instances_configuration.default_defined_tags
+ freeform_tags = each.value.freeform_tags != null ? each.value.freeform_tags : var.cluster_instances_configuration.default_freeform_tags
+
+ # instance_id and source are relevant when the instance configuration is created based on a EXISTING instance (when instance_details attribute is not provided)
+ instance_id = contains(keys(oci_core_instance.these),each.value.template_instance_id) ? oci_core_instance.these[each.value.template_instance_id].id : (length(regexall("^ocid1.*$", each.value.template_instance_id)) > 0 ? each.value.template_instance_id : var.instances_dependency[each.value.template_instance_id].id)
+ source = each.value.template_instance_id != null ? "INSTANCE" : "NONE"
+
+ ### instance_details {
+ #Required
+ ###vinstance_type = coalesce(each.value.instance_type,"compute")
+
+ #Optional
+ # block_volumes {
+
+ # #Optional
+ # attach_details {
+ # #Required
+ # type = var.instance_configuration_instance_details_block_volumes_attach_details_type
+
+ # #Optional
+ # device = var.instance_configuration_instance_details_block_volumes_attach_details_device
+ # display_name = var.instance_configuration_instance_details_block_volumes_attach_details_display_name
+ # is_pv_encryption_in_transit_enabled = var.instance_configuration_instance_details_block_volumes_attach_details_is_pv_encryption_in_transit_enabled
+ # is_read_only = var.instance_configuration_instance_details_block_volumes_attach_details_is_read_only
+ # is_shareable = var.instance_configuration_instance_details_block_volumes_attach_details_is_shareable
+ # use_chap = var.instance_configuration_instance_details_block_volumes_attach_details_use_chap
+ # }
+ # create_details {
+
+ # #Optional
+ # autotune_policies {
+ # #Required
+ # autotune_type = var.instance_configuration_instance_details_block_volumes_create_details_autotune_policies_autotune_type
+
+ # #Optional
+ # max_vpus_per_gb = var.instance_configuration_instance_details_block_volumes_create_details_autotune_policies_max_vpus_per_gb
+ # }
+ # availability_domain = var.instance_configuration_instance_details_block_volumes_create_details_availability_domain
+ # backup_policy_id = data.oci_core_volume_backup_policies.test_volume_backup_policies.volume_backup_policies.0.id
+ # block_volume_replicas {
+ # #Required
+ # availability_domain = var.instance_configuration_instance_details_block_volumes_create_details_block_volume_replicas_availability_domain
+
+ # #Optional
+ # display_name = var.instance_configuration_instance_details_block_volumes_create_details_block_volume_replicas_display_name
+ # }
+ # compartment_id = var.compartment_id
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_block_volumes_create_details_display_name
+ # freeform_tags = {"Department"= "Finance"}
+ # is_auto_tune_enabled = var.instance_configuration_instance_details_block_volumes_create_details_is_auto_tune_enabled
+ # kms_key_id = oci_kms_key.test_key.id
+ # size_in_gbs = var.instance_configuration_instance_details_block_volumes_create_details_size_in_gbs
+ # source_details {
+ # #Required
+ # type = var.instance_configuration_instance_details_block_volumes_create_details_source_details_type
+
+ # #Optional
+ # id = var.instance_configuration_instance_details_block_volumes_create_details_source_details_id
+ # }
+ # vpus_per_gb = var.instance_configuration_instance_details_block_volumes_create_details_vpus_per_gb
+ # }
+ # volume_id = oci_core_volume.test_volume.id
+ # }
+
+ # launch_details is relevant when the instance configuration is created based on a NEW instance (when instance_details attribute is provided).
+ ### dynamic "launch_details" {
+ ### for_each = each.value.instance_details != null ? [1] : []
+ ### content {
+ #Optional
+ # agent_config {
+
+ # #Optional
+ # are_all_plugins_disabled = var.instance_configuration_instance_details_launch_details_agent_config_are_all_plugins_disabled
+ # is_management_disabled = var.instance_configuration_instance_details_launch_details_agent_config_is_management_disabled
+ # is_monitoring_disabled = var.instance_configuration_instance_details_launch_details_agent_config_is_monitoring_disabled
+ # plugins_config {
+
+ # #Optional
+ # desired_state = var.instance_configuration_instance_details_launch_details_agent_config_plugins_config_desired_state
+ # name = var.instance_configuration_instance_details_launch_details_agent_config_plugins_config_name
+ # }
+ # }
+ # availability_config {
+
+ # #Optional
+ # is_live_migration_preferred = var.instance_configuration_instance_details_launch_details_availability_config_is_live_migration_preferred
+ # recovery_action = var.instance_configuration_instance_details_launch_details_availability_config_recovery_action
+ # }
+ # availability_domain = var.instance_configuration_instance_details_launch_details_availability_domain
+ # capacity_reservation_id = oci_core_capacity_reservation.test_capacity_reservation.id
+ ### compartment_id = each.value.instance_details.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.instance_details.compartment_id)) > 0 ? each.value.instance_details.compartment_id : var.compartments_dependency[each.value.instance_details.compartment_id].id) : (each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (length(regexall("^ocid1.*$", var.cluster_instances_configuration.default_compartment_id)) > 0 ? var.cluster_instances_configuration.default_compartment_id : var.compartments_dependency[var.cluster_instances_configuration.default_compartment_id].id))
+
+ # #Optional
+ # assign_ipv6ip = var.instance_configuration_instance_details_launch_details_create_vnic_details_assign_ipv6ip
+ # assign_private_dns_record = var.instance_configuration_instance_details_launch_details_create_vnic_details_assign_private_dns_record
+ # assign_public_ip = var.instance_configuration_instance_details_launch_details_create_vnic_details_assign_public_ip
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_launch_details_create_vnic_details_display_name
+ # freeform_tags = {"Department"= "Finance"}
+ # hostname_label = var.instance_configuration_instance_details_launch_details_create_vnic_details_hostname_label
+ # ipv6address_ipv6subnet_cidr_pair_details {
+
+ # #Optional
+ # ipv6address = var.instance_configuration_instance_details_launch_details_create_vnic_details_ipv6address_ipv6subnet_cidr_pair_details_ipv6address
+ # ipv6subnet_cidr = var.instance_configuration_instance_details_launch_details_create_vnic_details_ipv6address_ipv6subnet_cidr_pair_details_ipv6subnet_cidr
+ # }
+ # nsg_ids = var.instance_configuration_instance_details_launch_details_create_vnic_details_nsg_ids
+ # private_ip = var.instance_configuration_instance_details_launch_details_create_vnic_details_private_ip
+ # skip_source_dest_check = var.instance_configuration_instance_details_launch_details_create_vnic_details_skip_source_dest_check
+ # subnet_id = oci_core_subnet.test_subnet.id
+ # }
+ # dedicated_vm_host_id = oci_core_dedicated_vm_host.test_dedicated_vm_host.id
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_launch_details_display_name
+ # extended_metadata = var.instance_configuration_instance_details_launch_details_extended_metadata
+ # fault_domain = var.instance_configuration_instance_details_launch_details_fault_domain
+ # freeform_tags = {"Department"= "Finance"}
+ # instance_options {
+
+ # #Optional
+ # are_legacy_imds_endpoints_disabled = var.instance_configuration_instance_details_launch_details_instance_options_are_legacy_imds_endpoints_disabled
+ # }
+ # ipxe_script = var.instance_configuration_instance_details_launch_details_ipxe_script
+ # is_pv_encryption_in_transit_enabled = var.instance_configuration_instance_details_launch_details_is_pv_encryption_in_transit_enabled
+ # launch_mode = var.instance_configuration_instance_details_launch_details_launch_mode
+ # launch_options {
+
+ # #Optional
+ # boot_volume_type = var.instance_configuration_instance_details_launch_details_launch_options_boot_volume_type
+ # firmware = var.instance_configuration_instance_details_launch_details_launch_options_firmware
+ # is_consistent_volume_naming_enabled = var.instance_configuration_instance_details_launch_details_launch_options_is_consistent_volume_naming_enabled
+ # is_pv_encryption_in_transit_enabled = var.instance_configuration_instance_details_launch_details_launch_options_is_pv_encryption_in_transit_enabled
+ # network_type = var.instance_configuration_instance_details_launch_details_launch_options_network_type
+ # remote_data_volume_type = var.instance_configuration_instance_details_launch_details_launch_options_remote_data_volume_type
+ # }
+ # metadata = var.instance_configuration_instance_details_launch_details_metadata
+ # platform_config {
+ # #Required
+ # type = var.instance_configuration_instance_details_launch_details_platform_config_type
+
+ # #Optional
+ # are_virtual_instructions_enabled = var.instance_configuration_instance_details_launch_details_platform_config_are_virtual_instructions_enabled
+ # config_map = var.instance_configuration_instance_details_launch_details_platform_config_config_map
+ # is_access_control_service_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_access_control_service_enabled
+ # is_input_output_memory_management_unit_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_input_output_memory_management_unit_enabled
+ # is_measured_boot_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_measured_boot_enabled
+ # is_memory_encryption_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_memory_encryption_enabled
+ # is_secure_boot_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_secure_boot_enabled
+ # is_symmetric_multi_threading_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_symmetric_multi_threading_enabled
+ # is_trusted_platform_module_enabled = var.instance_configuration_instance_details_launch_details_platform_config_is_trusted_platform_module_enabled
+ # numa_nodes_per_socket = var.instance_configuration_instance_details_launch_details_platform_config_numa_nodes_per_socket
+ # percentage_of_cores_enabled = var.instance_configuration_instance_details_launch_details_platform_config_percentage_of_cores_enabled
+ # }
+ # preemptible_instance_config {
+
+ # #Optional
+ # preemption_action {
+ # #Required
+ # type = var.instance_configuration_instance_details_launch_details_preemptible_instance_config_preemption_action_type
+
+ # #Optional
+ # preserve_boot_volume = var.instance_configuration_instance_details_launch_details_preemptible_instance_config_preemption_action_preserve_boot_volume
+ # }
+ # }
+ # preferred_maintenance_action = var.instance_configuration_instance_details_launch_details_preferred_maintenance_action
+ ### shape = local.supported_shapes[lower(each.value.instance_details.shape)]
+ # shape_config {
+
+ # #Optional
+ # baseline_ocpu_utilization = var.instance_configuration_instance_details_launch_details_shape_config_baseline_ocpu_utilization
+ # memory_in_gbs = var.instance_configuration_instance_details_launch_details_shape_config_memory_in_gbs
+ # nvmes = var.instance_configuration_instance_details_launch_details_shape_config_nvmes
+ # ocpus = var.instance_configuration_instance_details_launch_details_shape_config_ocpus
+ # vcpus = var.instance_configuration_instance_details_launch_details_shape_config_vcpus
+ # }
+ ### source_details {
+ ### source_type = coalesce(each.value.instance_details.source_type,"image")
+
+ # #Optional
+ # boot_volume_id = oci_core_boot_volume.test_boot_volume.id
+ # boot_volume_size_in_gbs = var.instance_configuration_instance_details_launch_details_source_details_boot_volume_size_in_gbs
+ # boot_volume_vpus_per_gb = var.instance_configuration_instance_details_launch_details_source_details_boot_volume_vpus_per_gb
+ ### image_id = lower(coalesce(each.value.instance_details.source_type,"image")) == "image" ? each.value.instance_details.image_id : null
+ # kms_key_id = oci_kms_key.test_key.id
+ # instance_source_image_filter_details {
+
+ # #Optional
+ # compartment_id = var.compartment_id
+ # defined_tags_filter = var.instance_configuration_instance_details_launch_details_source_details_instance_source_image_filter_details_defined_tags_filter
+ # operating_system = var.instance_configuration_instance_details_launch_details_source_details_instance_source_image_filter_details_operating_system
+ # operating_system_version = var.instance_configuration_instance_details_launch_details_source_details_instance_source_image_filter_details_operating_system_version
+ # }
+ ### }
+ ### }
+
+ ### }
+ # options {
+
+ # #Optional
+ # block_volumes {
+
+ # #Optional
+ # attach_details {
+ # #Required
+ # type = var.instance_configuration_instance_details_options_block_volumes_attach_details_type
+
+ # #Optional
+ # device = var.instance_configuration_instance_details_options_block_volumes_attach_details_device
+ # display_name = var.instance_configuration_instance_details_options_block_volumes_attach_details_display_name
+ # is_pv_encryption_in_transit_enabled = var.instance_configuration_instance_details_options_block_volumes_attach_details_is_pv_encryption_in_transit_enabled
+ # is_read_only = var.instance_configuration_instance_details_options_block_volumes_attach_details_is_read_only
+ # is_shareable = var.instance_configuration_instance_details_options_block_volumes_attach_details_is_shareable
+ # use_chap = var.instance_configuration_instance_details_options_block_volumes_attach_details_use_chap
+ # }
+ # create_details {
+
+ # #Optional
+ # autotune_policies {
+ # #Required
+ # autotune_type = var.instance_configuration_instance_details_options_block_volumes_create_details_autotune_policies_autotune_type
+
+ # #Optional
+ # max_vpus_per_gb = var.instance_configuration_instance_details_options_block_volumes_create_details_autotune_policies_max_vpus_per_gb
+ # }
+ # availability_domain = var.instance_configuration_instance_details_options_block_volumes_create_details_availability_domain
+ # backup_policy_id = data.oci_core_volume_backup_policies.test_volume_backup_policies.volume_backup_policies.0.id
+ # compartment_id = var.compartment_id
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_options_block_volumes_create_details_display_name
+ # freeform_tags = {"Department"= "Finance"}
+ # kms_key_id = oci_kms_key.test_key.id
+ # size_in_gbs = var.instance_configuration_instance_details_options_block_volumes_create_details_size_in_gbs
+ # source_details {
+ # #Required
+ # type = var.instance_configuration_instance_details_options_block_volumes_create_details_source_details_type
+
+ # #Optional
+ # id = var.instance_configuration_instance_details_options_block_volumes_create_details_source_details_id
+ # }
+ # vpus_per_gb = var.instance_configuration_instance_details_options_block_volumes_create_details_vpus_per_gb
+ # }
+ # volume_id = oci_core_volume.test_volume.id
+ # }
+ # launch_details {
+
+ # #Optional
+ # agent_config {
+
+ # #Optional
+ # are_all_plugins_disabled = var.instance_configuration_instance_details_options_launch_details_agent_config_are_all_plugins_disabled
+ # is_management_disabled = var.instance_configuration_instance_details_options_launch_details_agent_config_is_management_disabled
+ # is_monitoring_disabled = var.instance_configuration_instance_details_options_launch_details_agent_config_is_monitoring_disabled
+ # plugins_config {
+
+ # #Optional
+ # desired_state = var.instance_configuration_instance_details_options_launch_details_agent_config_plugins_config_desired_state
+ # name = var.instance_configuration_instance_details_options_launch_details_agent_config_plugins_config_name
+ # }
+ # }
+ # availability_config {
+
+ # #Optional
+ # recovery_action = var.instance_configuration_instance_details_options_launch_details_availability_config_recovery_action
+ # }
+ # availability_domain = var.instance_configuration_instance_details_options_launch_details_availability_domain
+ # capacity_reservation_id = oci_core_capacity_reservation.test_capacity_reservation.id
+ # compartment_id = var.compartment_id
+ # create_vnic_details {
+
+ # #Optional
+ # assign_ipv6ip = var.instance_configuration_instance_details_launch_details_create_vnic_details_assign_ipv6ip
+ # assign_private_dns_record = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_assign_private_dns_record
+ # assign_public_ip = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_assign_public_ip
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_display_name
+ # freeform_tags = {"Department"= "Finance"}
+ # hostname_label = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_hostname_label
+ # ipv6address_ipv6subnet_cidr_pair_details {
+
+ # #Optional
+ # ipv6address = var.instance_configuration_instance_details_launch_details_create_vnic_details_ipv6address_ipv6subnet_cidr_pair_details_ipv6address
+ # ipv6subnet_cidr = var.instance_configuration_instance_details_launch_details_create_vnic_details_ipv6address_ipv6subnet_cidr_pair_details_ipv6subnet_cidr
+ # }
+ # nsg_ids = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_nsg_ids
+ # private_ip = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_private_ip
+ # skip_source_dest_check = var.instance_configuration_instance_details_options_launch_details_create_vnic_details_skip_source_dest_check
+ # subnet_id = oci_core_subnet.test_subnet.id
+ # }
+ # dedicated_vm_host_id = oci_core_dedicated_vm_host.test_dedicated_vm_host.id
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_options_launch_details_display_name
+ # extended_metadata = var.instance_configuration_instance_details_options_launch_details_extended_metadata
+ # fault_domain = var.instance_configuration_instance_details_options_launch_details_fault_domain
+ # freeform_tags = {"Department"= "Finance"}
+ # instance_options {
+
+ # #Optional
+ # are_legacy_imds_endpoints_disabled = var.instance_configuration_instance_details_options_launch_details_instance_options_are_legacy_imds_endpoints_disabled
+ # }
+ # ipxe_script = var.instance_configuration_instance_details_options_launch_details_ipxe_script
+ # is_pv_encryption_in_transit_enabled = var.instance_configuration_instance_details_options_launch_details_is_pv_encryption_in_transit_enabled
+ # launch_mode = var.instance_configuration_instance_details_options_launch_details_launch_mode
+ # launch_options {
+
+ # #Optional
+ # boot_volume_type = var.instance_configuration_instance_details_options_launch_details_launch_options_boot_volume_type
+ # firmware = var.instance_configuration_instance_details_options_launch_details_launch_options_firmware
+ # is_consistent_volume_naming_enabled = var.instance_configuration_instance_details_options_launch_details_launch_options_is_consistent_volume_naming_enabled
+ # is_pv_encryption_in_transit_enabled = var.instance_configuration_instance_details_options_launch_details_launch_options_is_pv_encryption_in_transit_enabled
+ # network_type = var.instance_configuration_instance_details_options_launch_details_launch_options_network_type
+ # remote_data_volume_type = var.instance_configuration_instance_details_options_launch_details_launch_options_remote_data_volume_type
+ # }
+ # metadata = var.instance_configuration_instance_details_options_launch_details_metadata
+ # platform_config {
+ # #Required
+ # type = var.instance_configuration_instance_details_options_launch_details_platform_config_type
+
+ # #Optional
+ # are_virtual_instructions_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_are_virtual_instructions_enabled
+ # is_access_control_service_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_access_control_service_enabled
+ # is_input_output_memory_management_unit_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_input_output_memory_management_unit_enabled
+ # is_measured_boot_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_measured_boot_enabled
+ # is_memory_encryption_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_memory_encryption_enabled
+ # is_secure_boot_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_secure_boot_enabled
+ # is_symmetric_multi_threading_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_symmetric_multi_threading_enabled
+ # is_trusted_platform_module_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_is_trusted_platform_module_enabled
+ # numa_nodes_per_socket = var.instance_configuration_instance_details_options_launch_details_platform_config_numa_nodes_per_socket
+ # percentage_of_cores_enabled = var.instance_configuration_instance_details_options_launch_details_platform_config_percentage_of_cores_enabled
+ # }
+ # preemptible_instance_config {
+
+ # #Optional
+ # preemption_action {
+ # #Required
+ # type = var.instance_configuration_instance_details_options_launch_details_preemptible_instance_config_preemption_action_type
+
+ # #Optional
+ # preserve_boot_volume = var.instance_configuration_instance_details_options_launch_details_preemptible_instance_config_preemption_action_preserve_boot_volume
+ # }
+ # }
+ # preferred_maintenance_action = var.instance_configuration_instance_details_options_launch_details_preferred_maintenance_action
+ # shape = var.instance_configuration_instance_details_options_launch_details_shape
+ # shape_config {
+
+ # #Optional
+ # baseline_ocpu_utilization = var.instance_configuration_instance_details_options_launch_details_shape_config_baseline_ocpu_utilization
+ # memory_in_gbs = var.instance_configuration_instance_details_options_launch_details_shape_config_memory_in_gbs
+ # nvmes = var.instance_configuration_instance_details_options_launch_details_shape_config_nvmes
+ # ocpus = var.instance_configuration_instance_details_options_launch_details_shape_config_ocpus
+ # vcpus = var.instance_configuration_instance_details_options_launch_details_shape_config_vcpus
+ # }
+ # source_details {
+ # #Required
+ # source_type = var.instance_configuration_instance_details_options_launch_details_source_details_source_type
+
+ # #Optional
+ # boot_volume_id = oci_core_boot_volume.test_boot_volume.id
+ # boot_volume_size_in_gbs = var.instance_configuration_instance_details_options_launch_details_source_details_boot_volume_size_in_gbs
+ # boot_volume_vpus_per_gb = var.instance_configuration_instance_details_options_launch_details_source_details_boot_volume_vpus_per_gb
+ # image_id = oci_core_image.test_image.id
+ # instance_source_image_filter_details {
+
+ # #Optional
+ # compartment_id = var.compartment_id
+ # defined_tags_filter = var.instance_configuration_instance_details_options_launch_details_source_details_instance_source_image_filter_details_defined_tags_filter
+ # operating_system = var.instance_configuration_instance_details_options_launch_details_source_details_instance_source_image_filter_details_operating_system
+ # operating_system_version = var.instance_configuration_instance_details_options_launch_details_source_details_instance_source_image_filter_details_operating_system_version
+ # }
+ # }
+ # }
+ # secondary_vnics {
+
+ # #Optional
+ # create_vnic_details {
+
+ # #Optional
+ # assign_ipv6ip = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_assign_ipv6ip
+ # assign_private_dns_record = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_assign_private_dns_record
+ # assign_public_ip = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_assign_public_ip
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_display_name
+ # freeform_tags = {"Department"= "Finance"}
+ # hostname_label = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_hostname_label
+ # ipv6address_ipv6subnet_cidr_pair_details {
+
+ # #Optional
+ # ipv6address = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_ipv6address_ipv6subnet_cidr_pair_details_ipv6address
+ # ipv6subnet_cidr = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_ipv6address_ipv6subnet_cidr_pair_details_ipv6subnet_cidr
+ # }
+ # nsg_ids = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_nsg_ids
+ # private_ip = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_private_ip
+ # skip_source_dest_check = var.instance_configuration_instance_details_options_secondary_vnics_create_vnic_details_skip_source_dest_check
+ # subnet_id = oci_core_subnet.test_subnet.id
+ # }
+ # display_name = var.instance_configuration_instance_details_options_secondary_vnics_display_name
+ # nic_index = var.instance_configuration_instance_details_options_secondary_vnics_nic_index
+ # }
+ # }
+ # secondary_vnics {
+
+ # #Optional
+ # create_vnic_details {
+
+ # #Optional
+ # assign_private_dns_record = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_assign_private_dns_record
+ # assign_public_ip = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_assign_public_ip
+ # defined_tags = {"Operations.CostCenter"= "42"}
+ # display_name = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_display_name
+ # freeform_tags = {"Department"= "Finance"}
+ # hostname_label = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_hostname_label
+ # nsg_ids = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_nsg_ids
+ # private_ip = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_private_ip
+ # skip_source_dest_check = var.instance_configuration_instance_details_secondary_vnics_create_vnic_details_skip_source_dest_check
+ # subnet_id = oci_core_subnet.test_subnet.id
+ # }
+ # display_name = var.instance_configuration_instance_details_secondary_vnics_display_name
+ # nic_index = var.instance_configuration_instance_details_secondary_vnics_nic_index
+ # }
+ ### }
+}
\ No newline at end of file
diff --git a/cis-compute-storage/clusters.tf b/cis-compute-storage/clusters.tf
new file mode 100644
index 0000000..cdd50ac
--- /dev/null
+++ b/cis-compute-storage/clusters.tf
@@ -0,0 +1,86 @@
+# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+data "oci_identity_availability_domains" "cluster_ads" {
+ for_each = var.clusters_configuration != null ? (var.clusters_configuration.clusters != null ? var.clusters_configuration.clusters : {}) : {}
+ compartment_id = each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (length(regexall("^ocid1.*$", var.clusters_configuration.default_compartment_id)) > 0 ? var.clusters_configuration.default_compartment_id : var.compartments_dependency[var.clusters_configuration.default_compartment_id].id)
+}
+
+locals {
+ cluster_networks = { for k, v in (var.clusters_configuration != null ? (var.clusters_configuration.clusters != null ? var.clusters_configuration.clusters : {}) : {}) : k => v if lower(coalesce(v.type,"cluster_network")) == "cluster_network"}
+ compute_clusters = { for k, v in (var.clusters_configuration != null ? (var.clusters_configuration.clusters != null ? var.clusters_configuration.clusters : {}) : {}) : k => v if lower(coalesce(v.type,"cluster_network")) != "cluster_network"}
+}
+
+resource "oci_core_cluster_network" "these" {
+ for_each = local.cluster_networks
+ lifecycle {
+ ## Check 1: cluster_network_settings is required for clusters of type "cluster_network".
+ precondition {
+ condition = lower(coalesce(each.value.type,"cluster_network")) == "cluster_network" && each.value.cluster_network_settings == null ? false : true
+ error_message = "VALIDATION FAILURE in cluster \"${each.key}\": \"cluster_network_settings\" is required for clusters of type \"${lower(coalesce(each.value.type,"cluster_network"))}\"."
+ }
+ }
+ #Required
+ compartment_id = each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (length(regexall("^ocid1.*$", var.clusters_configuration.default_compartment_id)) > 0 ? var.clusters_configuration.default_compartment_id : var.compartments_dependency[var.clusters_configuration.default_compartment_id].id)
+ instance_pools {
+ #Required
+ instance_configuration_id = contains(keys(oci_core_instance_configuration.these),each.value.cluster_network_settings.instance_configuration_id) ? oci_core_instance_configuration.these[each.value.cluster_network_settings.instance_configuration_id].id : (length(regexall("^ocid1.*$", each.value.cluster_network_settings.instance_configuration_id)) > 0 ? each.value.cluster_network_settings.instance_configuration_id : null)
+ size = each.value.cluster_network_settings.instance_pool != null ? coalesce(each.value.cluster_network_settings.instance_pool.size,1) : 1
+
+ #Optional
+ display_name = each.value.cluster_network_settings.instance_pool != null ? each.value.cluster_network_settings.instance_pool.name : null
+ defined_tags = each.value.defined_tags != null ? each.value.defined_tags : var.clusters_configuration.default_defined_tags
+ freeform_tags = each.value.freeform_tags != null ? each.value.freeform_tags : var.clusters_configuration.default_freeform_tags
+ }
+ placement_configuration {
+ #Required
+ availability_domain = data.oci_identity_availability_domains.cluster_ads[each.key].availability_domains[coalesce(each.value.availability_domain,1) - 1].name
+ primary_vnic_subnets {
+ #Required
+ subnet_id = length(regexall("^ocid1.*$", each.value.cluster_network_settings.networking.subnet_id)) > 0 ? each.value.cluster_network_settings.networking.subnet_id : var.network_dependency["subnets"][each.value.cluster_network_settings.networking.subnet_id].id
+ is_assign_ipv6ip = coalesce(each.value.cluster_network_settings.networking.ipv6_enable,false)
+ dynamic "ipv6address_ipv6subnet_cidr_pair_details" {
+ for_each = coalesce(each.value.cluster_network_settings.networking.ipv6_enable,false) ? coalesce(each.value.cluster_network_settings.networking.ipv6_subnet_cidrs,[]) : []
+ content {
+ ipv6subnet_cidr = each.key
+ }
+ }
+ }
+ dynamic "secondary_vnic_subnets" {
+ for_each = each.value.cluster_network_settings.networking.secondary_vnic_settings != null ? [1] : []
+ content {
+ subnet_id = length(regexall("^ocid1.*$", each.value.cluster_network_settings.networking.secondary_vnic_settings.subnet_id)) > 0 ? each.value.cluster_network_settings.networking.secondary_vnic_settings.subnet_id : var.network_dependency["subnets"][each.value.cluster_network_settings.networking.secondary_vnic_settings.subnet_id].id
+ display_name = each.value.cluster_network_settings.networking.secondary_vnic_settings.name
+ is_assign_ipv6ip = coalesce(each.value.cluster_network_settings.networking.secondary_vnic_settings.ipv6_enable,false)
+ dynamic "ipv6address_ipv6subnet_cidr_pair_details" {
+ for_each = coalesce(each.value.cluster_network_settings.networking.secondary_vnic_settings.ipv6_enable,false) ? coalesce(each.value.cluster_network_settings.networking.secondary_vnic_settings.ipv6_subnet_cidrs,[]) : []
+ content {
+ ipv6subnet_cidr = each.key
+ }
+ }
+ }
+ }
+ }
+
+ #Optional
+ # cluster_configuration {
+ # #Required
+ # hpc_island_id = oci_core_hpc_island.test_hpc_island.id
+
+ # #Optional
+ # network_block_ids = var.cluster_network_cluster_configuration_network_block_ids
+ # }
+
+ display_name = each.value.name
+ defined_tags = each.value.defined_tags != null ? each.value.defined_tags : var.clusters_configuration.default_defined_tags
+ freeform_tags = each.value.freeform_tags != null ? each.value.freeform_tags : var.clusters_configuration.default_freeform_tags
+}
+
+resource "oci_core_compute_cluster" "these" {
+ for_each = local.compute_clusters
+ compartment_id = each.value.compartment_id != null ? (length(regexall("^ocid1.*$", each.value.compartment_id)) > 0 ? each.value.compartment_id : var.compartments_dependency[each.value.compartment_id].id) : (length(regexall("^ocid1.*$", var.clusters_configuration.default_compartment_id)) > 0 ? var.clusters_configuration.default_compartment_id : var.compartments_dependency[var.clusters_configuration.default_compartment_id].id)
+ availability_domain = data.oci_identity_availability_domains.cluster_ads[each.key].availability_domains[coalesce(each.value.availability_domain, 1) - 1].name
+ display_name = each.value.name
+ defined_tags = each.value.defined_tags != null ? each.value.defined_tags : var.clusters_configuration.default_defined_tags
+ freeform_tags = each.value.freeform_tags != null ? each.value.freeform_tags : var.clusters_configuration.default_freeform_tags
+}
\ No newline at end of file
diff --git a/cis-compute-storage/compute.tf b/cis-compute-storage/compute.tf
index d9580fb..4f7c4dc 100644
--- a/cis-compute-storage/compute.tf
+++ b/cis-compute-storage/compute.tf
@@ -170,9 +170,10 @@ resource "oci_core_instance" "these" {
}
}
metadata = {
- ssh_authorized_keys = each.value.ssh_public_key_path != null ? file(each.value.ssh_public_key_path) : file(var.instances_configuration.default_ssh_public_key_path)
- # user_data = contains(keys(data.template_cloudinit_config.config),each.key) ? data.template_cloudinit_config.config[each.key].rendered : null
+ ssh_authorized_keys = each.value.ssh_public_key_path != null ? (fileexists(each.value.ssh_public_key_path) ? file(each.value.ssh_public_key_path) : each.value.ssh_public_key_path) : var.instances_configuration.default_ssh_public_key_path != null ? (fileexists(var.instances_configuration.default_ssh_public_key_path) ? file(var.instances_configuration.default_ssh_public_key_path) : var.instances_configuration.default_ssh_public_key_path): null
+ user_data = contains(keys(data.template_file.cloud_config),each.key) ? base64encode(data.template_file.cloud_config[each.key].rendered) : null
}
+ compute_cluster_id = each.value.cluster_id != null ? (contains(keys(oci_core_compute_cluster.these),each.value.cluster_id) ? oci_core_compute_cluster.these[each.value.cluster_id].id : (length(regexall("^ocid1.*$", each.value.cluster_id)) > 0 ? each.value.cluster_id : null)) : null
}
resource "oci_core_volume_backup_policy_assignment" "these_boot_volumes" {
@@ -181,6 +182,11 @@ resource "oci_core_volume_backup_policy_assignment" "these_boot_volumes" {
policy_id = local.oracle_backup_policies[lower(each.value.boot_volume != null ? each.value.boot_volume.backup_policy : "bronze")]
}
+data "template_file" "cloud_config" {
+ for_each = var.instances_configuration != null ? {for k, v in var.instances_configuration["instances"] : k => v if v.cloud_init != null || var.instances_configuration.default_cloud_init_heredoc_script != null || var.instances_configuration.default_cloud_init_script_file != null} : {}
+ template = coalesce(try(each.value.cloud_init.heredoc_script,null), try(file(try(each.value.cloud_init.script_file,null)),null), var.instances_configuration.default_cloud_init_heredoc_script, try(file(var.instances_configuration.default_cloud_init_script_file),null), "__void__")
+}
+
/* data "template_file" "block_volumes_templates" {
for_each = var.instances_configuration != null ? {for k, v in var.instances_configuration["instances"] : k => v if v.device_mounting != null} : {}
template = file("${path.module}/userdata/linux_mount.sh")
@@ -190,19 +196,7 @@ resource "oci_core_volume_backup_policy_assignment" "these_boot_volumes" {
block_vol_att_type = each.value.device_mounting.emulation_type != null ? lower(each.value.device_mounting.emulation_type) : "paravirtualized"
}
}
-
-data "template_cloudinit_config" "config" {
- for_each = var.instances_configuration != null ? {for k, v in var.instances_configuration["instances"] : k => v if v.device_mounting != null} : {}
- gzip = false
- base64_encode = true
-
- # Main cloud-config configuration file.
- part {
- filename = "cloudinit.sh"
- content_type = "text/x-shellscript"
- content = data.template_file.block_volumes_templates[each.key].rendered
- }
- } */
+*/
data "oci_core_vnic_attachments" "these" {
for_each = var.instances_configuration != null ? var.instances_configuration["instances"] : {}
diff --git a/cis-compute-storage/examples/cluster-networks/README.md b/cis-compute-storage/examples/cluster-networks/README.md
new file mode 100644
index 0000000..030632a
--- /dev/null
+++ b/cis-compute-storage/examples/cluster-networks/README.md
@@ -0,0 +1,40 @@
+# CIS Cluster Network Example
+
+## Introduction
+This example shows how to deploy an RDMA cluster network in OCI using the [cis-compute-storage module](../../). It deploys one Compute instance, one cluster instance configuration, and one cluster network with the characteristics described below. Refer to [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+A [cluster network](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/managingclusternetworks.htm) is a pool of high performance computing (HPC) instances that are connected with a high-bandwidth, ultra low-latency network. They're designed for highly demanding parallel computing jobs.
+
+### Compute Instance
+- The deployed Compute instance is used as a template for the cluster instance configuration.
+- The Compute instance shape is "BM.Optimized3.36".
+- The Compute instance is created in the compartment and subnet specified by *default_compartment_id* and *default_subnet_id* attributes, respectively, within *instances_configuration* variable.
+
+Note that you must provide the image *name* and *publisher_name* for provisioning the Compute instance. Use the [marketplace-images module](../../../marketplace-images/) to obtain Marketplace images information based on a search filter. It will also return the image OCID that can be used instead of the image name/publisher pair.
+
+### Cluster Instance Configuration
+- A cluster instance configuration is created based on the Compute instance. This is indicated by *template_instance_id* attribute within *cluster_instances_configuration* variable.
+- The cluster instance configuration is created in the compartment specified by *default_compartment_id* attribute within *cluster_instances_configuration* variable.
+
+### Cluster Instance Pool
+- A cluster instance pool is created based on the provided cluster instance configuration.
+
+### RDMA Cluster Network
+- An RDMA cluster network with one cluster instance pool of size 1.
+- The cluster instance pool size is specified by *instance_pool size* attribute within *clusters_configuration* variable.
+- The cluster network is created in the compartment specified by *default_compartment_id* attribute within *clusters_configuration* variable.
+
+## Using this example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-compute-storage module README.md](../../README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
\ No newline at end of file
diff --git a/cis-compute-storage/examples/cluster-networks/input.auto.tfvars.template b/cis-compute-storage/examples/cluster-networks/input.auto.tfvars.template
new file mode 100644
index 0000000..79c63a2
--- /dev/null
+++ b/cis-compute-storage/examples/cluster-networks/input.auto.tfvars.template
@@ -0,0 +1,90 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+private_key_path = "" # This is the full path on your local system to the API signing private key.
+private_key_password = "" # This is the password that protects the private key, if any.
+region = "" # The region name.
+
+#---------------------------------------
+# Input variables
+#---------------------------------------
+
+# This variable defines the RDMA clusters configuration.
+# The clusters attribute allows for the definition of an arbitrary number of clusters.
+clusters_configuration = {
+ default_compartment_id = ""
+ clusters = {
+ "CLUSTER-NETWORK" = {
+ name = "basic-cluster-network"
+ type = "cluster_network"
+ availability_domain = 2
+ cluster_network_settings = {
+ instance_configuration_id = "INSTANCE-CONFIG"
+ instance_pool = {
+ size = 1
+ }
+ networking = {
+ subnet_id = ""
+ ipv6_enable = true
+ }
+ }
+ }
+ }
+}
+
+# This variable defines the instances configuration that clusters are built on.
+# The configurations attribute allows for the definition of an arbitrary number of configurations.
+# Each configuration must provide a template_instance_id attribute, which value must be the key of a Compute instance within the instances_configuration variable above.
+cluster_instances_configuration = {
+ default_compartment_id = ""
+ configurations = {
+ INSTANCE-CONFIG = {
+ name = "cluster-instance-configuration"
+ template_instance_id = "CLUSTER-NETWORK-INSTANCE"
+ }
+ }
+}
+
+# This variable defines the Compute instances used as templates for the cluster.
+# The instances attribute allows for the definition of an arbitrary number on Compute instances.
+# Cluster networks require that Compute instance shapes is one of: "BM.Optimized3.36", "BM.HPC2.36", "BM.GPU.A100-v2.8", "BM.GPU4.8"
+instances_configuration = {
+ default_compartment_id = ""
+ default_subnet_id = ""
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ instances = {
+ CLUSTER-NETWORK-INSTANCE = {
+ shape = "BM.Optimized3.36"
+ name = "BM.Optimized3.36 Template Instance"
+ placement = {
+ availability_domain = 2
+ fault_domain = 2
+ }
+ boot_volume = {
+ size = 120
+ preserve_on_instance_deletion = false
+ }
+ networking = {
+ hostname = "bm-optimized336-template-instance"
+ network_security_groups = [""]
+ }
+ image = {
+ name = "Oracle Linux 7 STIG" # Marketplace image
+ publisher_name = "Oracle Linux"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/cluster-networks/main.tf b/cis-compute-storage/examples/cluster-networks/main.tf
new file mode 100644
index 0000000..45380e8
--- /dev/null
+++ b/cis-compute-storage/examples/cluster-networks/main.tf
@@ -0,0 +1,14 @@
+
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+module "cluster_networks" {
+ source = "../.."
+ providers = {
+ oci = oci
+ oci.block_volumes_replication_region = oci
+ }
+ clusters_configuration = var.clusters_configuration
+ cluster_instances_configuration = var.cluster_instances_configuration
+ instances_configuration = var.instances_configuration
+}
diff --git a/cis-compute-storage/examples/cluster-networks/providers.tf b/cis-compute-storage/examples/cluster-networks/providers.tf
new file mode 100644
index 0000000..eaa9dc8
--- /dev/null
+++ b/cis-compute-storage/examples/cluster-networks/providers.tf
@@ -0,0 +1,19 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+}
+
+terraform {
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+}
diff --git a/cis-compute-storage/examples/cluster-networks/variables.tf b/cis-compute-storage/examples/cluster-networks/variables.tf
new file mode 100644
index 0000000..0371fb5
--- /dev/null
+++ b/cis-compute-storage/examples/cluster-networks/variables.tf
@@ -0,0 +1,27 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+variable "tenancy_ocid" {}
+variable "region" {}
+variable "user_ocid" {}
+variable "fingerprint" {}
+variable "private_key_path" {}
+variable "private_key_password" {}
+
+variable "clusters_configuration" {
+ description = "RDMA clusters configuration attributes."
+ type = any
+ default = null
+}
+
+variable "cluster_instances_configuration" {
+ description = "RDMA cluster instances configuration attributes"
+ type = any
+ default = null
+}
+
+variable "instances_configuration" {
+ description = "Compute instances configuration attributes."
+ type = any
+ default = null
+}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/compute-block-volume/variables.tf b/cis-compute-storage/examples/compute-block-volume/variables.tf
index 56f94b2..97bdff3 100644
--- a/cis-compute-storage/examples/compute-block-volume/variables.tf
+++ b/cis-compute-storage/examples/compute-block-volume/variables.tf
@@ -15,189 +15,12 @@ variable "block_volumes_replication_region" {
variable "instances_configuration" {
description = "Compute instances configuration attributes."
- type = object({
- default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
- default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
- default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
-
- instances = map(object({ # the instances to manage in this configuration.
- cis_level = optional(string)
- compartment_id = optional(string) # the compartment where the instance is created. default_compartment_ocid is used if this is not defined.
- shape = string # the instance shape.
- name = string # the instance display name.
- platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
- image = object({ # the base image. You must provider either the id or (name and publisher name).
- id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
- name = optional(string) # the image name to search for in marketplace.
- publisher_name = optional(string) # the publisher name of the image name.
- })
- placement = optional(object({ # placement settings
- availability_domain = optional(number,1) # the instance availability domain. Default is 1.
- fault_domain = optional(number,1) # the instance fault domain. Default is 1.
- }))
- boot_volume = optional(object({ # boot volume settings
- type = optional(string,"paravirtualized") # boot volume emulation type. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio".
- firmware = optional(string) # firmware used to boot the VM. Valid options: "BIOS" (compatible with both 32 bit and 64 bit operating systems that boot using MBR style bootloaders), "UEFI_64" (default for platform images).
- size = optional(number,50) # boot volume size. Default is 50GB (minimum allowed by OCI).
- preserve_on_instance_deletion = optional(bool,true) # whether to preserve boot volume after deletion. Default is true.
- secure_boot = optional(bool, false) # prevents unauthorized boot loaders and operating systems from booting.
- measured_boot = optional(bool, false) # enhances boot security by taking and storing measurements of boot components, such as bootloaders, drivers, and operating systems. Bare metal instances do not support Measured Boot.
- trusted_platform_module = optional(bool, false) # used to securely store boot measurements.
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- }))
- volumes_emulation_type = optional(string,"paravirtualized") # Emulation type for attached storage volumes. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio". Module supported values for automated attachment: "paravirtualized", "iscsi".
- networking = optional(object({ # networking settings
- type = optional(string,"paravirtualized") # emulation type for the physical network interface card (NIC). Valid values: "paravirtualized" (default), "e1000", "vfio".
- private_ip = optional(string) # a private IP address of your choice to assign to the primary VNIC.
- hostname = optional(string) # the primary VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the primary VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the primary VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the primary VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the primary VNIC. Default is false.
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the primary VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- secondary_vnics = optional(map(object({
- display_name = optional(string) # the VNIC display name.
- private_ip = optional(string) # a private IP address of your choice to assign to the VNIC.
- hostname = optional(string) # the VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the VNIC. Default is false.
- nic_index = optional(number,0) # the physical network interface card (NIC) the VNIC will use. Defaults to 0. Certain bare metal instance shapes have two active physical NICs (0 and 1).
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- defined_tags = optional(map(string)) # VNIC defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # VNIC freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit_on_instance_create = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance creation time only.
- encrypt_in_transit_on_instance_update = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance update time only.
- encrypt_data_in_use = optional(bool, false) # whether the instance encrypts data in-use (in memory) while being processed. A.k.a confidential computing.
- }))
- flex_shape_settings = optional(object({ # flex shape settings
- memory = optional(number,16) # the instance memory for Flex shapes. Default is 16GB.
- ocpus = optional(number,1) # the instance ocpus number for Flex shapes. Default is 1.
- }))
- cloud_agent = optional(object({ # Cloud Agent settings
- disable_management = optional(bool,false) # whether the management plugins should be disabled. These plugins are enabled by default in the Compute service.
- disable_monitoring = optional(bool,false) # whether the monitoring plugins should be disabled. These plugins are enabled by default in the Compute service.
- plugins = optional(list(object({ # list of plugins
- name = string # the plugin name. It must be a valid plugin name. The plugin names are available in https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm and in compute-only example(./examples/compute-only/input.auto.tfvars.template) as well.
- enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
- })))
- }))
- ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
- defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- })
+ type = any
default = null
}
variable "storage_configuration" {
description = "Storage configuration attributes."
- type = object({
- default_compartment_id = optional(string), # the default compartment where all resources are defined. It's overriden by the compartment_id attribute within each object.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string,"1"), # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the frreform_tags attribute within each object.
-
- block_volumes = optional(map(object({ # the block volumes to manage in this configuration.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the compartment where the block volume is created. default_compartment_id is used if this is not defined.
- display_name = string # the name of the block volume.
- availability_domain = optional(number,1) # the availability domain where to create the block volume.
- volume_size = optional(number,50) # the size of the block volume.
- vpus_per_gb = optional(number,0) # the number of vpus per gb. Values are 0(LOW), 10(BALANCE), 20(HIGH), 30-120(ULTRA HIGH)
- attach_to_instances = optional(list(object({ # map to where to attach the block volume.
- instance_id = string # the instance that this volume will be attached to.
- device_name = string # where to mount the block volume. Should be one of the values from disk_mappings in the instance_configuration.
- attachment_type = optional(string,"paravirtualized") # the block volume attachment type. Valid values: "paravirtualized" (default), "iscsi".
- read_only = optional(bool,false) # whether the attachment is read_only or read/write.
- })))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit = optional(bool,false) # whether the block volume should encrypt traffic. Works only with paravirtualized attachment type. Default is false.
- }))
- replication = optional(object({ # replication settings
- availability_domain = number # the availability domain (AD) to replicate the volume. The AD is picked from the region specified by 'block_volumes_replication_region' variable if defined. Otherwise picked from the region specified by 'region' variable.
- }))
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- defined_tags = optional(map(string)) # block volume defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # block volume freeform_tags. default_freeform_tags is used if this is not defined.
- }))),
-
- file_storage = optional(object({ # file storage settings.
- default_subnet_id = optional(string), # the default subnet used for all file system mount targets. It's overriden by the subnet_id attribute within each mount_target object.
- file_systems = map(object({ # the file systems.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the file system compartment. default_compartment_id is used if this is not defined.
- file_system_name = string # the file_system name.
- availability_domain = optional(number,1) # the file system availability domain..
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- replication = optional(object({ # replication settings
- is_target = optional(bool,false) # whether the file system is a replication target. Default is false
- file_system_target_id = optional(string) # the file system replication target. It must be an existing unexported file system, in the same or in a different region than the source file system.
- interval_in_minutes = optional(number,60) # time interval (in minutes) between replication snapshots. Default is 60 minutes.
- }))
- snapshot_policy_id = optional(string) # the snapshot policy identifying key in the snapshots_policy map. A default snapshot policy is associated with file systems without a snapshot policy.
- defined_tags = optional(map(string)) # file system defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # file system freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- mount_targets = optional(map(object({ # the mount targets.
- compartment_id = optional(string) # the mount target compartment. default_compartment_id is used if this is not defined.
- mount_target_name = string # the mount target and export set name.
- availability_domain = optional(number,1) # the mount target availability domain.
- subnet_id = optional(string) # the mount target subnet. default_subnet_id is used if this is not defined.
- exports = optional(list(object({
- path = string # export path. For example: /foo
- file_system_id = string # the file system identifying key the export applies to. It must be one of the keys in file_systems map of objects.
- options = optional(list(object({ # optional export options.
- source = string # the source IP or CIDR allowed to access the mount target.
- access = optional(string, "READ_ONLY") # type of access grants. Valid values (case sensitive): READ_WRITE, READ_ONLY.
- identity = optional(string, "NONE") # UID and GID remapped to. Valid values(case sensitive): ALL, ROOT, NONE.
- use_privileged_source_port = optional(bool, true) # If true, accessing the file system through this export must connect from a privileged source port.
- })))
- })))
- })))
- snapshot_policies = optional(map(object({
- name = string
- compartment_id = optional(string)
- availability_domain = optional(number,1)
- prefix = optional(string)
- schedules = optional(list(object({
- period = string # "DAILY", "WEEKLY", "MONTHLY", "YEARLY"
- prefix = optional(string)
- time_zone = optional(string,"UTC")
- hour_of_day = optional(number,23)
- day_of_week = optional(string)
- day_of_month = optional(number)
- month = optional(string)
- retention_in_seconds = optional(number)
- start_time = optional(string)
- })))
- defined_tags = optional(map(string)) # snapshot policy defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # snapshot policy freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- })
+ type = any
default = null
}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/compute-clusters/README.md b/cis-compute-storage/examples/compute-clusters/README.md
new file mode 100644
index 0000000..9c4df59
--- /dev/null
+++ b/cis-compute-storage/examples/compute-clusters/README.md
@@ -0,0 +1,40 @@
+# OCI Compute Cluster Example
+
+## Introduction
+This example shows how to deploy RDMA cluster networks in OCI using the [cis-compute-storage module](../../). It deploys one Compute instance, one cluster instance configuration, and one cluster network with the characteristics described below. Refer to [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+A [Compute cluster](https://docs.oracle.com/iaas/Content/Compute/Tasks/compute-clusters.htm) is a remote direct memory access (RDMA) network group. You can create high performance computing (HPC) instances in the network and manage them individually.
+
+### Compute Instance
+- The deployed Compute instance is used as a template for the cluster instance configuration.
+- The Compute instance shape is "BM.Optimized3.36".
+- The Compute instance is created in the compartment and subnet specified by *default_compartment_id* and *default_subnet_id* attributes, respectively, within *instances_configuration* variable.
+
+Note that you must provide the image *name* and *publisher_name* for provisioning the Compute instance. Use the [marketplace-images module](../../../marketplace-images/) to obtain Marketplace images information based on a search filter. It will also return the image OCID that can be used instead of the image name/publisher pair.
+
+### Cluster Instance Configuration
+- A cluster instance configuration is created based on the Compute instance. This is indicated by *template_instance_id* attribute within *cluster_instances_configuration* variable.
+- The cluster instance configuration is created in the compartment specified by *default_compartment_id* attribute within *cluster_instances_configuration* variable.
+
+### Cluster Instance Pool
+- A cluster instance pool is created based on the provided cluster instance configuration.
+
+### RDMA Cluster Network
+- An RDMA cluster network with one cluster instance pool of size 1.
+- The cluster instance pool size is specified by *instance_pool size* attribute within *clusters_configuration* variable.
+- The cluster network is created in the compartment specified by *default_compartment_id* attribute within *clusters_configuration* variable.
+
+## Using this example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-compute-storage module README.md](../../README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
\ No newline at end of file
diff --git a/cis-compute-storage/examples/compute-clusters/input.auto.tfvars.template b/cis-compute-storage/examples/compute-clusters/input.auto.tfvars.template
new file mode 100644
index 0000000..70da17a
--- /dev/null
+++ b/cis-compute-storage/examples/compute-clusters/input.auto.tfvars.template
@@ -0,0 +1,66 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+private_key_path = "" # This is the full path on your local system to the API signing private key.
+private_key_password = "" # This is the password that protects the private key, if any.
+region = "" # The region name.
+
+#---------------------------------------
+# Input variables
+#---------------------------------------
+
+clusters_configuration = {
+ default_compartment_id = ""
+ clusters = {
+ "COMPUTE-CLUSTER" = {
+ type = "compute"
+ name = "basic-compute-cluster"
+ availability_domain = 3
+ }
+ }
+}
+
+instances_configuration = {
+ default_compartment_id = ""
+ default_subnet_id = ""
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ instances = {
+ COMPUTE-CLUSTER-INSTANCE = {
+ shape = "BM.Optimized3.36"
+ name = "BM.Optimized3.36-instance"
+ cluster_id = "COMPUTE-CLUSTER"
+ placement = {
+ availability_domain = 3
+ fault_domain = 3
+ }
+ boot_volume = {
+ size = 120
+ preserve_on_instance_deletion = false
+ }
+ networking = {
+ hostname = "bm-optimized3-36-instance"
+ network_security_groups = [""]
+ }
+ image = {
+ name = "Oracle Linux 7 STIG" # Marketplace image
+ publisher_name = "Oracle Linux"
+ }
+ }
+ }
+}
+
+
+
diff --git a/cis-compute-storage/examples/compute-clusters/main.tf b/cis-compute-storage/examples/compute-clusters/main.tf
new file mode 100644
index 0000000..45380e8
--- /dev/null
+++ b/cis-compute-storage/examples/compute-clusters/main.tf
@@ -0,0 +1,14 @@
+
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+module "cluster_networks" {
+ source = "../.."
+ providers = {
+ oci = oci
+ oci.block_volumes_replication_region = oci
+ }
+ clusters_configuration = var.clusters_configuration
+ cluster_instances_configuration = var.cluster_instances_configuration
+ instances_configuration = var.instances_configuration
+}
diff --git a/cis-compute-storage/examples/compute-clusters/providers.tf b/cis-compute-storage/examples/compute-clusters/providers.tf
new file mode 100644
index 0000000..eaa9dc8
--- /dev/null
+++ b/cis-compute-storage/examples/compute-clusters/providers.tf
@@ -0,0 +1,19 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+}
+
+terraform {
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+}
diff --git a/cis-compute-storage/examples/compute-clusters/variables.tf b/cis-compute-storage/examples/compute-clusters/variables.tf
new file mode 100644
index 0000000..0371fb5
--- /dev/null
+++ b/cis-compute-storage/examples/compute-clusters/variables.tf
@@ -0,0 +1,27 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+variable "tenancy_ocid" {}
+variable "region" {}
+variable "user_ocid" {}
+variable "fingerprint" {}
+variable "private_key_path" {}
+variable "private_key_password" {}
+
+variable "clusters_configuration" {
+ description = "RDMA clusters configuration attributes."
+ type = any
+ default = null
+}
+
+variable "cluster_instances_configuration" {
+ description = "RDMA cluster instances configuration attributes"
+ type = any
+ default = null
+}
+
+variable "instances_configuration" {
+ description = "Compute instances configuration attributes."
+ type = any
+ default = null
+}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/compute-only-multiple-vnics/variables.tf b/cis-compute-storage/examples/compute-only-multiple-vnics/variables.tf
index 085c8d0..3bf66ee 100644
--- a/cis-compute-storage/examples/compute-only-multiple-vnics/variables.tf
+++ b/cis-compute-storage/examples/compute-only-multiple-vnics/variables.tf
@@ -10,98 +10,6 @@ variable "private_key_password" { default = "" }
variable "instances_configuration" {
description = "Compute instances configuration attributes."
- type = object({
- default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
- default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
- default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
-
- instances = map(object({ # the instances to manage in this configuration.
- cis_level = optional(string)
- compartment_id = optional(string) # the compartment where the instance is created. default_compartment_ocid is used if this is not defined.
- shape = string # the instance shape.
- name = string # the instance display name.
- platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
- image = object({ # the base image. You must provider either the id or (name and publisher name).
- id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
- name = optional(string) # the image name to search for in marketplace.
- publisher_name = optional(string) # the publisher name of the image name.
- })
- placement = optional(object({ # placement settings
- availability_domain = optional(number,1) # the instance availability domain. Default is 1.
- fault_domain = optional(number,1) # the instance fault domain. Default is 1.
- }))
- boot_volume = optional(object({ # boot volume settings
- type = optional(string,"paravirtualized") # boot volume emulation type. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio".
- firmware = optional(string) # firmware used to boot the VM. Valid options: "BIOS" (compatible with both 32 bit and 64 bit operating systems that boot using MBR style bootloaders), "UEFI_64" (default for platform images).
- size = optional(number,50) # boot volume size. Default is 50GB (minimum allowed by OCI).
- preserve_on_instance_deletion = optional(bool,true) # whether to preserve boot volume after deletion. Default is true.
- secure_boot = optional(bool, false) # prevents unauthorized boot loaders and operating systems from booting.
- measured_boot = optional(bool, false) # enhances boot security by taking and storing measurements of boot components, such as bootloaders, drivers, and operating systems. Bare metal instances do not support Measured Boot.
- trusted_platform_module = optional(bool, false) # used to securely store boot measurements.
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- }))
- volumes_emulation_type = optional(string,"paravirtualized") # Emulation type for attached storage volumes. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio". Module supported values for automated attachment: "paravirtualized", "iscsi".
- networking = optional(object({ # networking settings
- type = optional(string,"paravirtualized") # emulation type for the physical network interface card (NIC). Valid values: "paravirtualized" (default), "e1000", "vfio".
- private_ip = optional(string) # a private IP address of your choice to assign to the primary VNIC.
- hostname = optional(string) # the primary VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the primary VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the primary VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the primary VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the primary VNIC. Default is false.
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the primary VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- secondary_vnics = optional(map(object({
- display_name = optional(string) # the VNIC display name.
- private_ip = optional(string) # a private IP address of your choice to assign to the VNIC.
- hostname = optional(string) # the VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the VNIC. Default is false.
- nic_index = optional(number,0) # the physical network interface card (NIC) the VNIC will use. Defaults to 0. Certain bare metal instance shapes have two active physical NICs (0 and 1).
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- defined_tags = optional(map(string)) # VNIC defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # VNIC freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit_on_instance_create = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance creation time only.
- encrypt_in_transit_on_instance_update = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance update time only.
- encrypt_data_in_use = optional(bool, false) # whether the instance encrypts data in-use (in memory) while being processed. A.k.a confidential computing.
- }))
- flex_shape_settings = optional(object({ # flex shape settings
- memory = optional(number,16) # the instance memory for Flex shapes. Default is 16GB.
- ocpus = optional(number,1) # the instance ocpus number for Flex shapes. Default is 1.
- }))
- cloud_agent = optional(object({ # Cloud Agent settings
- disable_management = optional(bool,false) # whether the management plugins should be disabled. These plugins are enabled by default in the Compute service.
- disable_monitoring = optional(bool,false) # whether the monitoring plugins should be disabled. These plugins are enabled by default in the Compute service.
- plugins = optional(list(object({ # list of plugins
- name = string # the plugin name. It must be a valid plugin name. The plugin names are available in https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm and in compute-only example(./examples/compute-only/input.auto.tfvars.template) as well.
- enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
- })))
- }))
- ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
- defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- })
+ type = any
default = null
}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/compute-only/README.md b/cis-compute-storage/examples/compute-only/README.md
index fdc9517..03fa468 100644
--- a/cis-compute-storage/examples/compute-only/README.md
+++ b/cis-compute-storage/examples/compute-only/README.md
@@ -11,10 +11,11 @@ For INSTANCE-1:
- The instance is based on "VM.Standard.E4.Flex" shape, as defined by the *shape* attribute.
- The instance is based on the "Oracle Linux 7 STIG" Marketplace image published by "Oracle Linux", as defined by *image.name* and *image.publisher_name* attributes. Use the [markeplace-images module](../../../marketplace-images/) to find Marketplace images information based on a search filter.
- The instance will **not** have the boot volume preserved on termination, as defined by *boot_volume.preserve_on_instance_deletion* attribute.
-- The instance requires a customer managed key for boot volume encryption, as defined by *cis_level* atrribute.
+- The instance requires a customer managed key for boot volume encryption, as defined by *cis_level* attribute.
- The instance boot volume is encrypted with a customer managed key referred by *encryption.kms_key_id* attribute.
- The instance boot volume is set to be backed up per Oracle-managed *bronze* backup policy (enforced by the module by default).
- The instance has all Cloud Agent plugins enabled, as defined by *cloud_agent.plugins* attribute.
+- The instance executes the cloud-init script given in [cloud-init.yaml](./cloud-init.yaml).
For INSTANCE-2:
- The instance is based on "VM.Standard.E4.Flex" shape, as defined by the *shape* attribute.
diff --git a/cis-compute-storage/examples/compute-only/cloud-init.yaml b/cis-compute-storage/examples/compute-only/cloud-init.yaml
new file mode 100644
index 0000000..cada072
--- /dev/null
+++ b/cis-compute-storage/examples/compute-only/cloud-init.yaml
@@ -0,0 +1,3 @@
+#cloud-config
+runcmd:
+ - echo 'This instance was provisioned by Terraform.' >> /etc/motd
\ No newline at end of file
diff --git a/cis-compute-storage/examples/compute-only/input.auto.tfvars.template b/cis-compute-storage/examples/compute-only/input.auto.tfvars.template
index ae642ab..805dd33 100644
--- a/cis-compute-storage/examples/compute-only/input.auto.tfvars.template
+++ b/cis-compute-storage/examples/compute-only/input.auto.tfvars.template
@@ -69,6 +69,15 @@ instances_configuration = {
{name = "Bastion", enabled = true}
]
}
+ cloud_init = {
+ script_file = "./cloud-init.yaml"
+## Comment the line above and uncomment the following five lines if you want provide the script inlined in heredoc style.
+# heredoc_script = <> /etc/motd
+# YAML
+ }
}
INSTANCE-2 = { # Shielded instance, per platform_type and boot_volume.measured_boot settings.
shape = "VM.Standard.E4.Flex"
diff --git a/cis-compute-storage/examples/compute-only/variables.tf b/cis-compute-storage/examples/compute-only/variables.tf
index 085c8d0..3bf66ee 100644
--- a/cis-compute-storage/examples/compute-only/variables.tf
+++ b/cis-compute-storage/examples/compute-only/variables.tf
@@ -10,98 +10,6 @@ variable "private_key_password" { default = "" }
variable "instances_configuration" {
description = "Compute instances configuration attributes."
- type = object({
- default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
- default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
- default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
-
- instances = map(object({ # the instances to manage in this configuration.
- cis_level = optional(string)
- compartment_id = optional(string) # the compartment where the instance is created. default_compartment_ocid is used if this is not defined.
- shape = string # the instance shape.
- name = string # the instance display name.
- platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
- image = object({ # the base image. You must provider either the id or (name and publisher name).
- id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
- name = optional(string) # the image name to search for in marketplace.
- publisher_name = optional(string) # the publisher name of the image name.
- })
- placement = optional(object({ # placement settings
- availability_domain = optional(number,1) # the instance availability domain. Default is 1.
- fault_domain = optional(number,1) # the instance fault domain. Default is 1.
- }))
- boot_volume = optional(object({ # boot volume settings
- type = optional(string,"paravirtualized") # boot volume emulation type. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio".
- firmware = optional(string) # firmware used to boot the VM. Valid options: "BIOS" (compatible with both 32 bit and 64 bit operating systems that boot using MBR style bootloaders), "UEFI_64" (default for platform images).
- size = optional(number,50) # boot volume size. Default is 50GB (minimum allowed by OCI).
- preserve_on_instance_deletion = optional(bool,true) # whether to preserve boot volume after deletion. Default is true.
- secure_boot = optional(bool, false) # prevents unauthorized boot loaders and operating systems from booting.
- measured_boot = optional(bool, false) # enhances boot security by taking and storing measurements of boot components, such as bootloaders, drivers, and operating systems. Bare metal instances do not support Measured Boot.
- trusted_platform_module = optional(bool, false) # used to securely store boot measurements.
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- }))
- volumes_emulation_type = optional(string,"paravirtualized") # Emulation type for attached storage volumes. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio". Module supported values for automated attachment: "paravirtualized", "iscsi".
- networking = optional(object({ # networking settings
- type = optional(string,"paravirtualized") # emulation type for the physical network interface card (NIC). Valid values: "paravirtualized" (default), "e1000", "vfio".
- private_ip = optional(string) # a private IP address of your choice to assign to the primary VNIC.
- hostname = optional(string) # the primary VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the primary VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the primary VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the primary VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the primary VNIC. Default is false.
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the primary VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- secondary_vnics = optional(map(object({
- display_name = optional(string) # the VNIC display name.
- private_ip = optional(string) # a private IP address of your choice to assign to the VNIC.
- hostname = optional(string) # the VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the VNIC. Default is false.
- nic_index = optional(number,0) # the physical network interface card (NIC) the VNIC will use. Defaults to 0. Certain bare metal instance shapes have two active physical NICs (0 and 1).
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- defined_tags = optional(map(string)) # VNIC defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # VNIC freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit_on_instance_create = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance creation time only.
- encrypt_in_transit_on_instance_update = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance update time only.
- encrypt_data_in_use = optional(bool, false) # whether the instance encrypts data in-use (in memory) while being processed. A.k.a confidential computing.
- }))
- flex_shape_settings = optional(object({ # flex shape settings
- memory = optional(number,16) # the instance memory for Flex shapes. Default is 16GB.
- ocpus = optional(number,1) # the instance ocpus number for Flex shapes. Default is 1.
- }))
- cloud_agent = optional(object({ # Cloud Agent settings
- disable_management = optional(bool,false) # whether the management plugins should be disabled. These plugins are enabled by default in the Compute service.
- disable_monitoring = optional(bool,false) # whether the monitoring plugins should be disabled. These plugins are enabled by default in the Compute service.
- plugins = optional(list(object({ # list of plugins
- name = string # the plugin name. It must be a valid plugin name. The plugin names are available in https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm and in compute-only example(./examples/compute-only/input.auto.tfvars.template) as well.
- enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
- })))
- }))
- ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
- defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- })
+ type = any
default = null
}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/external-dependencies/README.md b/cis-compute-storage/examples/external-dependencies/README.md
index a39bd53..f43d28c 100644
--- a/cis-compute-storage/examples/external-dependencies/README.md
+++ b/cis-compute-storage/examples/external-dependencies/README.md
@@ -67,8 +67,7 @@ The OCI Object Storage objects with external dependencies are expected to have s
```
{
"INSTANCE-2": {
- "id": "ocid1.instance.oc1.iad.anuwc...ftq",
- "is_pv_encryption_in_transit_enabled" : false
+ "id": "ocid1.instance.oc1.iad.anuwc...ftq"
}
}
```
diff --git a/cis-compute-storage/examples/external-dependencies/variables.tf b/cis-compute-storage/examples/external-dependencies/variables.tf
index b9c432f..6490872 100644
--- a/cis-compute-storage/examples/external-dependencies/variables.tf
+++ b/cis-compute-storage/examples/external-dependencies/variables.tf
@@ -15,190 +15,13 @@ variable "block_volumes_replication_region" {
variable "instances_configuration" {
description = "Compute instances configuration attributes."
- type = object({
- default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
- default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
- default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
-
- instances = map(object({ # the instances to manage in this configuration.
- cis_level = optional(string)
- compartment_id = optional(string) # the compartment where the instance is created. default_compartment_ocid is used if this is not defined.
- shape = string # the instance shape.
- name = string # the instance display name.
- platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
- image = object({ # the base image. You must provider either the id or (name and publisher name).
- id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
- name = optional(string) # the image name to search for in marketplace.
- publisher_name = optional(string) # the publisher name of the image name.
- })
- placement = optional(object({ # placement settings
- availability_domain = optional(number,1) # the instance availability domain. Default is 1.
- fault_domain = optional(number,1) # the instance fault domain. Default is 1.
- }))
- boot_volume = optional(object({ # boot volume settings
- type = optional(string,"paravirtualized") # boot volume emulation type. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio".
- firmware = optional(string) # firmware used to boot the VM. Valid options: "BIOS" (compatible with both 32 bit and 64 bit operating systems that boot using MBR style bootloaders), "UEFI_64" (default for platform images).
- size = optional(number,50) # boot volume size. Default is 50GB (minimum allowed by OCI).
- preserve_on_instance_deletion = optional(bool,true) # whether to preserve boot volume after deletion. Default is true.
- secure_boot = optional(bool, false) # prevents unauthorized boot loaders and operating systems from booting.
- measured_boot = optional(bool, false) # enhances boot security by taking and storing measurements of boot components, such as bootloaders, drivers, and operating systems. Bare metal instances do not support Measured Boot.
- trusted_platform_module = optional(bool, false) # used to securely store boot measurements.
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- }))
- volumes_emulation_type = optional(string,"paravirtualized") # Emulation type for attached storage volumes. Valid values: "paravirtualized" (default for platform images), "scsi", "iscsi", "ide", "vfio". Module supported values for automated attachment: "paravirtualized", "iscsi".
- networking = optional(object({ # networking settings
- type = optional(string,"paravirtualized") # emulation type for the physical network interface card (NIC). Valid values: "paravirtualized" (default), "e1000", "vfio".
- private_ip = optional(string) # a private IP address of your choice to assign to the primary VNIC.
- hostname = optional(string) # the primary VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the primary VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the primary VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the primary VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the primary VNIC. Default is false.
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the primary VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- secondary_vnics = optional(map(object({
- display_name = optional(string) # the VNIC display name.
- private_ip = optional(string) # a private IP address of your choice to assign to the VNIC.
- hostname = optional(string) # the VNIC hostname.
- assign_public_ip = optional(bool) # whether to assign the VNIC a public IP. Defaults to whether the subnet is public or private.
- subnet_id = optional(string) # the subnet where the VNIC is created. default_subnet_id is used if this is not defined.
- network_security_groups = optional(list(string)) # list of network security groups the VNIC should be placed into.
- skip_source_dest_check = optional(bool,false) # whether the source/destination check is disabled on the VNIC. Default is false.
- nic_index = optional(number,0) # the physical network interface card (NIC) the VNIC will use. Defaults to 0. Certain bare metal instance shapes have two active physical NICs (0 and 1).
- secondary_ips = optional(map(object({ # list of secondary private IP addresses for the VNIC.
- display_name = optional(string) # Secondary IP display name.
- hostname = optional(string) # Secondary IP host name.
- private_ip = optional(string) # Secondary IP address. If not provided, an IP address from the subnet is randomly chosen.
- defined_tags = optional(map(string)) # Secondary IP defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # Secondary IP freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- defined_tags = optional(map(string)) # VNIC defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # VNIC freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit_on_instance_create = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance creation time only.
- encrypt_in_transit_on_instance_update = optional(bool,null) # whether to enable in-transit encryption for the instance. Default is set by the underlying image. Applicable at instance update time only.
- encrypt_data_in_use = optional(bool, false) # whether the instance encrypts data in-use (in memory) while being processed. A.k.a confidential computing.
- }))
- flex_shape_settings = optional(object({ # flex shape settings
- memory = optional(number,16) # the instance memory for Flex shapes. Default is 16GB.
- ocpus = optional(number,1) # the instance ocpus number for Flex shapes. Default is 1.
- }))
- cloud_agent = optional(object({ # Cloud Agent settings
- disable_management = optional(bool,false) # whether the management plugins should be disabled. These plugins are enabled by default in the Compute service.
- disable_monitoring = optional(bool,false) # whether the monitoring plugins should be disabled. These plugins are enabled by default in the Compute service.
- plugins = optional(list(object({ # list of plugins
- name = string # the plugin name. It must be a valid plugin name. The plugin names are available in https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/manage-plugins.htm and in compute-only example(./examples/compute-only/input.auto.tfvars.template) as well.
- enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
- })))
- }))
- ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
- defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- })
+ type = any
default = null
}
variable "storage_configuration" {
description = "Storage configuration attributes."
- type = object({
- default_compartment_id = optional(string), # the default compartment where all resources are defined. It's overriden by the compartment_id attribute within each object.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string,"1"), # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the frreform_tags attribute within each object.
-
- block_volumes = optional(map(object({ # the block volumes to manage in this configuration.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the compartment where the block volume is created. default_compartment_id is used if this is not defined.
- display_name = string # the name of the block volume.
- availability_domain = optional(number,1) # the availability domain where to create the block volume.
- volume_size = optional(number,50) # the size of the block volume.
- vpus_per_gb = optional(number,0) # the number of vpus per gb. Values are 0(LOW), 10(BALANCE), 20(HIGH), 30-120(ULTRA HIGH)
- attach_to_instances = optional(list(object({ # map to where to attach the block volume.
- instance_id = string # the instance that this volume will be attached to.
- device_name = string # where to mount the block volume. Should be one of the values from disk_mappings in the instance_configuration.
- attachment_type = optional(string,"paravirtualized") # the block volume attachment type. Valid values: "paravirtualized" (default), "iscsi".
- read_only = optional(bool,false) # whether the attachment is "Read Only" or "Read/Write". Default is false, which means "Read/Write".
- })))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit = optional(bool,false) # whether the block volume should encrypt traffic. Works only with paravirtualized attachment type. Default is false.
- }))
- replication = optional(object({ # replication settings
- availability_domain = number # the availability domain (AD) to replicate the volume. The AD is picked from the region specified by 'block_volumes_replication_region' variable if defined. Otherwise picked from the region specified by 'region' variable.
- }))
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- defined_tags = optional(map(string)) # block volume defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # block volume freeform_tags. default_freeform_tags is used if this is not defined.
- }))),
-
- file_storage = optional(object({ # file storage settings.
- default_subnet_id = optional(string), # the default subnet used for all file system mount targets. It's overriden by the subnet_id attribute within each mount_target object.
- file_systems = map(object({ # the file systems.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the file system compartment. default_compartment_id is used if this is not defined.
- file_system_name = string # the file_system name.
- availability_domain = optional(number,1) # the file system availability domain..
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- replication = optional(object({ # replication settings
- is_target = optional(bool,false) # whether the file system is a replication target. Default is false
- file_system_target_id = optional(string) # the file system replication target. It must be an existing unexported file system, in the same or in a different region than the source file system.
- interval_in_minutes = optional(number,60) # time interval (in minutes) between replication snapshots. Default is 60 minutes.
- }))
- snapshot_policy_id = optional(string) # the snapshot policy identifying key in the snapshots_policy map. A default snapshot policy is associated with file systems without a snapshot policy.
- defined_tags = optional(map(string)) # file system defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # file system freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- mount_targets = optional(map(object({ # the mount targets.
- compartment_id = optional(string) # the mount target compartment. default_compartment_id is used if this is not defined.
- mount_target_name = string # the mount target and export set name.
- availability_domain = optional(number,1) # the mount target availability domain.
- subnet_id = optional(string) # the mount target subnet. default_subnet_id is used if this is not defined.
- exports = optional(list(object({
- path = string # export path. For example: /foo
- file_system_id = string # the file system identifying key the export applies to. It must be one of the keys in file_systems map of objects.
- options = optional(list(object({ # optional export options.
- source = string # the source IP or CIDR allowed to access the mount target.
- access = optional(string, "READ_ONLY") # type of access grants. Valid values (case sensitive): READ_WRITE, READ_ONLY.
- identity = optional(string, "NONE") # UID and GID remapped to. Valid values(case sensitive): ALL, ROOT, NONE.
- use_privileged_source_port = optional(bool, true) # If true, accessing the file system through this export must connect from a privileged source port.
- })))
- })))
- })))
- snapshot_policies = optional(map(object({
- name = string
- compartment_id = optional(string)
- availability_domain = optional(number,1)
- prefix = optional(string)
- schedules = optional(list(object({
- period = string # "DAILY", "WEEKLY", "MONTHLY", "YEARLY"
- prefix = optional(string)
- time_zone = optional(string,"UTC")
- hour_of_day = optional(number,23)
- day_of_week = optional(string)
- day_of_month = optional(number)
- month = optional(string)
- retention_in_seconds = optional(number)
- start_time = optional(string)
- })))
- defined_tags = optional(map(string)) # snapshot policy defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # snapshot policy freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- })
+ type = any
default = null
}
diff --git a/cis-compute-storage/examples/replica-file-system/variables.tf b/cis-compute-storage/examples/replica-file-system/variables.tf
index 7896dbf..828754c 100644
--- a/cis-compute-storage/examples/replica-file-system/variables.tf
+++ b/cis-compute-storage/examples/replica-file-system/variables.tf
@@ -10,91 +10,6 @@ variable "private_key_password" { default = "" }
variable "storage_configuration" {
description = "Storage configuration attributes."
- type = object({
- default_compartment_id = optional(string), # the default compartment where all resources are defined. It's overriden by the compartment_id attribute within each object.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string,"1"), # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the frreform_tags attribute within each object.
-
- block_volumes = optional(map(object({ # the block volumes to manage in this configuration.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the compartment where the block volume is created. default_compartment_id is used if this is not defined.
- display_name = string # the name of the block volume.
- availability_domain = optional(number,1) # the availability domain where to create the block volume.
- volume_size = optional(number,50) # the size of the block volume.
- vpus_per_gb = optional(number,0) # the number of vpus per gb. Values are 0(LOW), 10(BALANCE), 20(HIGH), 30-120(ULTRA HIGH)
- attach_to_instances = optional(list(object({ # map to where to attach the block volume.
- instance_id = string # the instance that this volume will be attached to.
- device_name = string # where to mount the block volume. Should be one of the values from disk_mappings in the instance_configuration.
- attachment_type = optional(string,"paravirtualized") # the block volume attachment type. Valid values: "paravirtualized" (default), "iscsi".
- read_only = optional(bool,false) # whether the attachment is read_only or read/write.
- })))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit = optional(bool,false) # whether the block volume should encrypt traffic. Works only with paravirtualized attachment type. Default is false.
- }))
- replication = optional(object({ # replication settings
- availability_domain = number # the availability domain (AD) to replicate the volume. The AD is picked from the region specified by 'block_volumes_replication_region' variable if defined. Otherwise picked from the region specified by 'region' variable.
- }))
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- defined_tags = optional(map(string)) # block volume defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # block volume freeform_tags. default_freeform_tags is used if this is not defined.
- }))),
-
- file_storage = optional(object({ # file storage settings.
- default_subnet_id = optional(string), # the default subnet used for all file system mount targets. It's overriden by the subnet_id attribute within each mount_target object.
- file_systems = map(object({ # the file systems.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the file system compartment. default_compartment_id is used if this is not defined.
- file_system_name = string # the file_system name.
- availability_domain = optional(number,1) # the file system availability domain..
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- replication = optional(object({ # replication settings
- is_target = optional(bool,false) # whether the file system is a replication target. Default is false
- file_system_target_id = optional(string) # the file system replication target. It must be an existing unexported file system, in the same or in a different region than the source file system.
- interval_in_minutes = optional(number,60) # time interval (in minutes) between replication snapshots. Default is 60 minutes.
- }))
- snapshot_policy_id = optional(string) # the snapshot policy identifying key in the snapshots_policy map. A default snapshot policy is associated with file systems without a snapshot policy.
- defined_tags = optional(map(string)) # file system defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # file system freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- mount_targets = optional(map(object({ # the mount targets.
- compartment_id = optional(string) # the mount target compartment. default_compartment_id is used if this is not defined.
- mount_target_name = string # the mount target and export set name.
- availability_domain = optional(number,1) # the mount target availability domain.
- subnet_id = optional(string) # the mount target subnet. default_subnet_id is used if this is not defined.
- exports = optional(list(object({
- path = string # export path. For example: /foo
- file_system_id = string # the file system identifying key the export applies to. It must be one of the keys in file_systems map of objects.
- options = optional(list(object({ # optional export options.
- source = string # the source IP or CIDR allowed to access the mount target.
- access = optional(string, "READ_ONLY") # type of access grants. Valid values (case sensitive): READ_WRITE, READ_ONLY.
- identity = optional(string, "NONE") # UID and GID remapped to. Valid values(case sensitive): ALL, ROOT, NONE.
- use_privileged_source_port = optional(bool, true) # If true, accessing the file system through this export must connect from a privileged source port.
- })))
- })))
- })))
- snapshot_policies = optional(map(object({
- name = string
- compartment_id = optional(string)
- availability_domain = optional(number,1)
- prefix = optional(string)
- schedules = optional(list(object({
- period = string # "DAILY", "WEEKLY", "MONTHLY", "YEARLY"
- prefix = optional(string)
- time_zone = optional(string,"UTC")
- hour_of_day = optional(number,23)
- day_of_week = optional(string)
- day_of_month = optional(number)
- month = optional(string)
- retention_in_seconds = optional(number)
- start_time = optional(string)
- })))
- defined_tags = optional(map(string)) # snapshot policy defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # snapshot policy freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- })
+ type = any
default = null
}
\ No newline at end of file
diff --git a/cis-compute-storage/examples/storage-only/variables.tf b/cis-compute-storage/examples/storage-only/variables.tf
index 8af5ed6..16dfa55 100644
--- a/cis-compute-storage/examples/storage-only/variables.tf
+++ b/cis-compute-storage/examples/storage-only/variables.tf
@@ -15,91 +15,6 @@ variable "block_volumes_replication_region" {
variable "storage_configuration" {
description = "Storage configuration attributes."
- type = object({
- default_compartment_id = optional(string), # the default compartment where all resources are defined. It's overriden by the compartment_id attribute within each object.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string,"1"), # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the frreform_tags attribute within each object.
-
- block_volumes = optional(map(object({ # the block volumes to manage in this configuration.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the compartment where the block volume is created. default_compartment_id is used if this is not defined.
- display_name = string # the name of the block volume.
- availability_domain = optional(number,1) # the availability domain where to create the block volume.
- volume_size = optional(number,50) # the size of the block volume.
- vpus_per_gb = optional(number,0) # the number of vpus per gb. Values are 0(LOW), 10(BALANCE), 20(HIGH), 30-120(ULTRA HIGH)
- attach_to_instances = optional(list(object({ # map to where to attach the block volume.
- instance_id = string # the instance that this volume will be attached to.
- device_name = string # where to mount the block volume. Should be one of the values from disk_mappings in the instance_configuration.
- attachment_type = optional(string,"paravirtualized") # the block volume attachment type. Valid values: "paravirtualized" (default), "iscsi".
- read_only = optional(bool,false) # whether the attachment is read_only or read/write.
- })))
- encryption = optional(object({ # encryption settings
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- encrypt_in_transit = optional(bool,false) # whether the block volume should encrypt traffic. Works only with paravirtualized attachment type. Default is false.
- }))
- replication = optional(object({ # replication settings
- availability_domain = number # the availability domain (AD) to replicate the volume. The AD is picked from the region specified by 'block_volumes_replication_region' variable if defined. Otherwise picked from the region specified by 'region' variable.
- }))
- backup_policy = optional(string,"bronze") # the Oracle managed backup policy. Valid values: "gold", "silver", "bronze". Default is "bronze".
- defined_tags = optional(map(string)) # block volume defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # block volume freeform_tags. default_freeform_tags is used if this is not defined.
- }))),
-
- file_storage = optional(object({ # file storage settings.
- default_subnet_id = optional(string), # the default subnet used for all file system mount targets. It's overriden by the subnet_id attribute within each mount_target object.
- file_systems = map(object({ # the file systems.
- cis_level = optional(string,"1")
- compartment_id = optional(string) # the file system compartment. default_compartment_id is used if this is not defined.
- file_system_name = string # the file_system name.
- availability_domain = optional(number,1) # the file system availability domain..
- kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
- replication = optional(object({ # replication settings
- is_target = optional(bool,false) # whether the file system is a replication target. Default is false
- file_system_target_id = optional(string) # the file system replication target. It must be an existing unexported file system, in the same or in a different region than the source file system.
- interval_in_minutes = optional(number,60) # time interval (in minutes) between replication snapshots. Default is 60 minutes.
- }))
- snapshot_policy_id = optional(string) # the snapshot policy identifying key in the snapshots_policy map. A default snapshot policy is associated with file systems without a snapshot policy.
- defined_tags = optional(map(string)) # file system defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # file system freeform_tags. default_freeform_tags is used if this is not defined.
- }))
- mount_targets = optional(map(object({ # the mount targets.
- compartment_id = optional(string) # the mount target compartment. default_compartment_id is used if this is not defined.
- mount_target_name = string # the mount target and export set name.
- availability_domain = optional(number,1) # the mount target availability domain.
- subnet_id = optional(string) # the mount target subnet. default_subnet_id is used if this is not defined.
- exports = optional(list(object({
- path = string # export path. For example: /foo
- file_system_id = string # the file system identifying key the export applies to. It must be one of the keys in file_systems map of objects.
- options = optional(list(object({ # optional export options.
- source = string # the source IP or CIDR allowed to access the mount target.
- access = optional(string, "READ_ONLY") # type of access grants. Valid values (case sensitive): READ_WRITE, READ_ONLY.
- identity = optional(string, "NONE") # UID and GID remapped to. Valid values(case sensitive): ALL, ROOT, NONE.
- use_privileged_source_port = optional(bool, true) # If true, accessing the file system through this export must connect from a privileged source port.
- })))
- })))
- })))
- snapshot_policies = optional(map(object({
- name = string
- compartment_id = optional(string)
- availability_domain = optional(number,1)
- prefix = optional(string)
- schedules = optional(list(object({
- period = string # "DAILY", "WEEKLY", "MONTHLY", "YEARLY"
- prefix = optional(string)
- time_zone = optional(string,"UTC")
- hour_of_day = optional(number,23)
- day_of_week = optional(string)
- day_of_month = optional(number)
- month = optional(string)
- retention_in_seconds = optional(number)
- start_time = optional(string)
- })))
- defined_tags = optional(map(string)) # snapshot policy defined_tags. default_defined_tags is used if this is not defined.
- freeform_tags = optional(map(string)) # snapshot policy freeform_tags. default_freeform_tags is used if this is not defined.
- })))
- }))
- })
+ type = any
default = null
}
\ No newline at end of file
diff --git a/cis-compute-storage/outputs.tf b/cis-compute-storage/outputs.tf
index 5f5a76f..8069b06 100644
--- a/cis-compute-storage/outputs.tf
+++ b/cis-compute-storage/outputs.tf
@@ -33,3 +33,13 @@ output "file_systems_mount_targets" {
output "file_systems_snapshot_policies" {
value = var.enable_output ? oci_file_storage_filesystem_snapshot_policy.these : null
}
+
+output "cluster_networks" {
+ description = "The cluster networks."
+ value = var.enable_output ? oci_core_cluster_network.these : null
+}
+
+output "compute_clusters" {
+ description = "The Compute clusters."
+ value = var.enable_output ? oci_core_compute_cluster.these : null
+}
\ No newline at end of file
diff --git a/cis-compute-storage/variables.tf b/cis-compute-storage/variables.tf
index f22ed25..28c2da5 100644
--- a/cis-compute-storage/variables.tf
+++ b/cis-compute-storage/variables.tf
@@ -4,13 +4,15 @@
variable "instances_configuration" {
description = "Compute instances configuration attributes."
type = object({
- default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
- default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
- default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
- default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
- default_cis_level = optional(string) # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
- default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
- default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
+ default_compartment_id = string, # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
+ default_subnet_id = optional(string), # the default subnet where all Compute instances are defined. It's overriden by the subnet_id attribute within each Compute instance.
+ default_ssh_public_key_path = optional(string), # the default ssh public key path used to access the Compute instance. It's overriden by the ssh_public_key attribute within each Compute instance.
+ default_kms_key_id = optional(string), # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
+ default_cis_level = optional(string) # the CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
+ default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
+ default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
+ default_cloud_init_heredoc_script = optional(string), # the default cloud-init script in Terraform heredoc style that is applied to all instances. It has precedence over default_cloud_init_script_file.
+ default_cloud_init_script_file = optional(string), # the default cloud-init script file that is applied to all instances.
instances = map(object({ # the instances to manage in this configuration.
cis_level = optional(string)
@@ -18,6 +20,7 @@ variable "instances_configuration" {
shape = string # the instance shape.
name = string # the instance display name.
platform_type = optional(string) # the platform type. Assigning this variable enables various platform security features in the Compute service. Valid values: "AMD_MILAN_BM", "AMD_MILAN_BM_GPU", "AMD_ROME_BM", "AMD_ROME_BM_GPU", "AMD_VM", "GENERIC_BM", "INTEL_ICELAKE_BM", "INTEL_SKYLAKE_BM", "INTEL_VM".
+ cluster_id = optional(string) # the Compute cluster the instance is added to. It can take either a literal cluster OCID or cluster key defined in the clusters_configuration variable.
image = object({ # the base image. You must provider either the id or (name and publisher name).
id = optional(string) # the base image id for creating the instance. It takes precedence over name and publisher_name.
name = optional(string) # the image name to search for in marketplace.
@@ -91,6 +94,10 @@ variable "instances_configuration" {
enabled = bool #Whether or not the plugin should be enabled. In order to disable a previously enabled plugin, set this value to false. Simply removing the plugin from the list will not disable it.
})))
}))
+ cloud_init = optional(object({
+ heredoc_script = optional(string) # the cloud-init script in Terraform heredoc style that is applied to the instance. It has precedence over script_file.
+ script_file = optional(string) # the cloud-init script file that is applied to the instance.
+ }))
ssh_public_key_path = optional(string) # the SSH public key path used to access the instance.
defined_tags = optional(map(string)) # instances defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # instances freeform_tags. default_freeform_tags is used if this is not defined.
@@ -190,6 +197,69 @@ variable "storage_configuration" {
default = null
}
+variable "clusters_configuration" {
+ description = "Clusters configuration attributes."
+ type = object({
+ default_compartment_id = optional(string), # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
+ default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
+ default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
+
+ clusters = map(object({ # the clusters to manage in this configuration.
+ type = optional(string) # the cluster type. Valid values: "cluster_network", "compute_cluster". Default is "cluster_network".
+ compartment_id = optional(string) # the compartment where the cluster is created. default_compartment_ocid is used if this is not defined.
+ availability_domain = optional(number) # the availability domain for cluster instances. Default is 1.
+ name = string # the cluster display name.
+ defined_tags = optional(map(string)) # clusters defined_tags. default_defined_tags is used if this is not defined.
+ freeform_tags = optional(map(string)) # clusters freeform_tags. default_freeform_tags is used if this is not defined.
+ cluster_network_settings = optional(object({ # cluster network settings. Only applicable if type is "cluster_network".
+ instance_configuration_id = string # the instance configuration id to use in this cluster.
+ instance_pool = optional(object({ # Cluster instance pool settings.
+ name = optional(string) # The instance pool name.
+ size = optional(number) # The number of instances in the instance pool. Defauls is 1.
+ }))
+ networking = object({
+ subnet_id = string # The subnet where instances primary VNIC is placed.
+ ipv6_enable = optional(bool) # Whether IPv6 is enabled for instances primary VNIC. Default is false.
+ ipv6_subnet_cidrs = optional(list(string)) # A list of IPv6 subnet CIDR ranges from which the primary VNIC is assigned an IPv6 address. Only applicable if ipv6_enable for primary VNIC is true. Default is [].
+ secondary_vnic_settings = optional(object({ # Secondary VNIC settings
+ subnet_id = string # The subnet where instances secondary VNIC are created.
+ name = optional(string) # The secondary VNIC name.
+ ipv6_enable = optional(bool) # Whether IPv6 is enabled for the secondary VNIC. Default is false.
+ ipv6_subnet_cidrs = optional(list(string)) # A list of IPv6 subnet CIDR ranges from which the secondary VNIC is assigned an IPv6 address. Only applicable if ipv6_enable for secondary VNIC is true. Default is [].
+ }))
+ })
+ }))
+ }))
+ })
+ default = null
+}
+
+variable "cluster_instances_configuration" {
+ description = "Cluster instances configuration attributes"
+ type = object({
+ default_compartment_id = optional(string) # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
+ default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
+ default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
+ #default_ssh_public_key_path = optional(string) # the default SSH public key path used to access the workers.
+ #default_kms_key_id = optional(string) # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
+ configurations = map(object({ # the instance configurations to manage in this configuration.
+ compartment_id = optional(string) # the compartment where the instance configuration is created. default_compartment_id is used if this is not defined.
+ name = optional(string) # the instance configuration display name.
+ instance_type = optional(string) # the instance type. Default is "compute".
+ # instance_details = optional(object({ # The instance details to use as the configuration template. If provided, an instance is created and used as template for all instances in the cluster instance pool.
+ # shape = optional(string) # the instance shape. Default is "BM.Optimized3.36".
+ # source_type = optional(string)
+ # image_id = optional(string) # the image id used to boot the instance.
+ # compartment_id = optional(string) # the instance compartment. It defaults to the configuration compartment_id if undefined.
+ # }))
+ template_instance_id = optional(string) # the existing instance id to use as the configuration template for all instances in the cluster instance pool.
+ defined_tags = optional(map(string)) # instance configuration defined_tags. default_defined_tags is used if this is not defined.
+ freeform_tags = optional(map(string)) # instance configuration freeform_tags. default_freeform_tags is used if this is not defined.
+ }))
+ })
+ default = null
+}
+
variable "enable_output" {
description = "Whether Terraform should enable the module output."
type = bool
@@ -202,33 +272,49 @@ variable "module_name" {
default = "cis-compute-storage"
}
-variable compartments_dependency {
+variable "compartments_dependency" {
description = "A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the compartment OCID) of string type."
- type = map(any)
+ type = map(object({
+ id = string # the compartment OCID
+ }))
default = null
}
-variable network_dependency {
- description = "A map of objects containing the externally managed network resources this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the network resource OCID) of string type."
- type = map(any)
+variable "network_dependency" {
+ description = "An object containing the externally managed network resources this module may depend on. Supported resources are 'subnets', and 'network_security_groups', represented as map of objects. Each object, when defined, must have an 'id' attribute of string type set with the subnet or NSG OCID."
+ type = object({
+ subnets = optional(map(object({
+ id = string # the subnet OCID
+ })))
+ network_security_groups = optional(map(object({
+ id = string # the NSG OCID
+ })))
+ })
default = null
}
-variable kms_dependency {
+variable "kms_dependency" {
description = "A map of objects containing the externally managed encryption keys this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the key OCID) of string type."
- type = map(any)
+ type = map(object({
+ id = string # the key OCID.
+ }))
default = null
}
-variable instances_dependency {
- description = "A map of objects containing the externally managed Compute instances this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the instance OCID) of string type."
- type = map(any)
+variable "instances_dependency" {
+ description = "A map of objects containing the externally managed Compute instances this module may depend on. The objects, when defined, must contain at least an 'id' attribute (representing the instance OCID) of string type."
+ type = map(object({
+ id = string # the instance OCID
+ }))
default = null
}
-variable file_system_dependency {
+
+variable "file_system_dependency" {
description = "A map of objects containing the externally managed file storage resources this module may depend on. This is used when setting file system replication using target file systems managed in another Terraform configuration. All map objects must have the same type and must contain at least an 'id' attribute (representing the file system OCID) of string type."
- type = map(any)
+ type = map(object({
+ id = string # the file system OCID.
+ }))
default = null
}
diff --git a/cis-oke/README.md b/cis-oke/README.md
new file mode 100644
index 0000000..cdb54c1
--- /dev/null
+++ b/cis-oke/README.md
@@ -0,0 +1,314 @@
+# Oracle Cloud Infrastructure (OCI) Terraform CIS OKE Module
+
+![Landing Zone logo](../landing_zone_300.png)
+
+This module manages Container Engine For Kubernetes (OKE) clusters, node pools and virtual node pools in Oracle Cloud Infrastructure (OCI). OKE is a fully-managed, scalable, and highly available service that you can use to deploy your containerized applications to the cloud.
+
+The module supports bringing in external dependencies that managed resources depend on, including compartments, subnets, network security groups, encryption keys, and others.
+
+Check [module specification](./SPEC.md) for a full description of module requirements, supported variables, managed resources and outputs.
+
+Check the [examples](./examples/) folder for actual module usage.
+
+- [Features](#features)
+- [Requirements](#requirements)
+- [How to Invoke the Module](#invoke)
+- [Module Functioning](#functioning)
+ - [OKE Clusters](#oke)
+ - [Node Pools](#node-pools)
+ - [Virtual Node Pools](#virtual-node-pools)
+ - [External Dependencies](#ext-dep)
+- [Related Documentation](#related)
+- [Known Issues](#issues)
+
+## Features
+The following features are currently supported by the module:
+
+- Basic and Enhanced clusters;
+- Standard node pools and virtual node pools;
+- Kubernetes secrets encryption with customer managed keys enforced, driven by CIS profile level "2".
+- Worker nodes image signing enforced, driven by CIS profile level "2".
+- Boot volumes encryption at rest enforced, driven by CIS profile level "2".
+- Boot volumes in-transit encryption enforced, drive by CIS profile level "2".
+
+## Requirements
+### IAM Permissions
+
+This module requires the following IAM permissions:
+
+For deploying OKE Clusters:
+```
+Allow group to manage cluster-family in compartment
+Allow group to manage instance-family in compartment
+Allow group to use vnics in compartment
+Allow group to inspect compartments in compartment
+Allow group to read virtual-network-family in compartment
+Allow group to use subnets in compartment
+Allow group to use network-security-groups in compartment
+Allow group to use vnics in compartment
+Allow group to manage private-ips in compartment
+Allow group to manage public-ips in compartment
+```
+
+For allowing load balancers deployments by OKE clusters:
+```
+Allow any-user to use private-ips in compartment where all { request.principal.type = 'cluster', request.principal.compartment.id = '' }
+Allow any-user to use network-security-groups in compartment where all { request.principal.type = 'cluster', request.principal.compartment.id = '' }
+Allow any-user to use subnets in compartment where all { request.principal.type = 'cluster', request.principal.compartment.id = '' }
+```
+
+For cluster auto-scaling:
+```
+Allow any-user to manage instances in compartment where all { request.principal.type = 'cluster', request.principal.compartment.id = '' }
+```
+
+For more information about OKE Policies [click here](https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengpolicyconfig.htm#Policy_Configuration_for_Cluster_Creation_and_Deployment).
+
+### Terraform Version > 1.3.x
+
+This module relies on [Terraform Optional Object Type Attributes feature](https://developer.hashicorp.com/terraform/language/expressions/type-constraints#optional-object-type-attributes), which has been promoted and no longer experimental in versions greater than 1.3.x. The feature shortens the amount of input values in complex object types, by having Terraform automatically inserting a default value for any missing optional attributes.
+
+## How to Invoke the Module
+
+Terraform modules can be invoked locally or remotely.
+
+For invoking the module locally, just set the module *source* attribute to the module file path (relative path works). The following example assumes the module is two folders up in the file system.
+```
+module "oke" {
+ source = "../.."
+ clusters_configuration = var.clusters_configuration
+ workers_configuration = var.workers_configuration
+}
+```
+For invoking the module remotely, set the module *source* attribute to the *cis-oke* module folder in this repository, as shown:
+```
+module "oke" {
+ source = "github.com/oracle-quickstart/terraform-oci-secure-workloads/cis-oke"
+ clusters_configuration = var.clusters_configuration
+ workers_configuration = var.workers_configuration
+}
+```
+For referring to a specific module version, add an extra slash before the folder name and append *ref=\* to the *source* attribute value, as in:
+```
+ source = "github.com/oracle-quickstart/terraform-oci-secure-workloads//cis-oke?ref=v0.1.0"
+```
+
+## Module Functioning
+
+The module defines two top level variables used to manage OKE clusters and node pools:
+- **clusters_configuration**: for managing OKE clusters.
+- **workers_configuration**: for managing node pools and virtual node pools.
+
+### OKE Clusters
+
+OKE Clusters are managed using the **clusters_configuration** object. It contains a set of attributes starting with the prefix **default_** and one attribute named **clusters**. The **default_** attribute values are applied to all clusters within **clusters**, unless overridden at the cluster level.
+
+The *default_* attributes are the following:
+- **default_compartment_id**: Default compartment for all clusters. It can be overridden by *compartment_id* attribute in each cluster. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_img_kms_key_id**: (Optional) Default image signing key for all clusters. It can be overridden by *img_kms_key_id* attribute in each cluster. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *kms_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_kube_secret_kms_key_id**: (Optional) Default kube secret encryption key for all clusters. It can be overridden by *kube_secret_kms_key_id* attribute in each cluster. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *kms_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_cis_level**: (Optional) Default CIS OCI Benchmark profile level for all clusters. Level "2" enforces usage of customer managed keys for image signing and kube secrets encryption. Default is "1". It can be overridden by *cis_level* attribute in each cluster.
+- **default_defined_tags**: (Optional) Default defined tags for all clusters. It can be overridden by *defined_tags* attribute in each cluster.
+- **default_freeform_tags**: (Optional) Default freeform tags for all clusters. It can be overridden by *freeform_tags* attribute in each cluster.
+
+The clusters themselves are defined within the **clusters** attribute. In Terraform terms, it is a map of objects, where each object is referred by an identifying key. The supported attributes are listed below. For better usability, most attributes are grouped in logical blocks. They are properly indented in the list.
+- **compartment_id**: (Optional) The cluster compartment. *default_compartment_id* is used if undefined. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **cis_level**: (Optional) The CIS OCI Benchmark profile level to apply. *default_cis_level* is used if undefined.
+- **kubernetes_version**: (Optional) the kubernetes version. If not specified, the latest version is selected.
+- **name**: the cluster display name.
+- **is_enhanced**:(Optional) If the cluster is enhanced. It is designed to work only with native CNI. Default is basic.
+- **cni_type**: (Optional) The CNI type of the cluster. It can be either flannel or native. Default is flannel.
+- **defined_tags**: (Optional) Clusters defined_tags. *default_defined_tags* is used if undefined.
+- **freeform_tags**: (Optional) Clusters freeform_tags. *default_freeform_tags* is used if undefined.
+- **options**: (Optional) Options attributes for the cluster.
+ - **add_ons**: (Optional) Configurable cluster addons.
+ - **dashboard_enabled**: (Optional) Whether Kubernetes dashboard is enabled. Default is false.
+ - **tiller_enabled**: (Optional) Whether Tiller is enabled. Default is false.
+ - **admission_controller**: (Optional) Configurable cluster admission controllers.
+ - **pod_policy_enabled**: (Optional) Whether the pod policy is enabled. Default is false.
+ - **kubernetes_network_config**: (Optional) Pods and services network configuration for kubernetes.
+ - **pods_cidr**: (Optional) The CIDR block for Kubernetes pods. Optional, defaults to *10.244.0.0/16*.
+ - **services_cidr**: (Optional) The CIDR block for Kubernetes services. Optional, defaults to *10.96.0.0/16*.
+ - **persistent_volume_config**: (Optional) Configuration to be applied to block volumes created by Kubernetes Persistent Volume Claims (PVC).
+ - **defined_tags**: (Optional) PVC defined_tags. *default_defined_tags* is used if undefined.
+ - **freeform_tags**: (Optional) PVC freeform_tags. *default_freeform_tags* is used if undefined.
+ - **service_lb_config**: (Optional) Configuration to be applied to load balancers created by Kubernetes services.
+ - **defined_tags**: (Ooptional) Load balancer defined_tags. *default_defined_tags* is used if undefined.
+ - **freeform_tags**: (Optional) Load balancer freeform_tags. *default_freeform_tags* is used if undefined.
+- **networking**: (Optional) Cluster networking settings.
+ - **vcn_id**: The vcn where the cluster is created. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **is_api_endpoint_public**: (Optional) Whether the OKE API endpoint is public. Default is false.
+ - **api_endpoint_nsg_ids**: (Optional) The NSGss used by the OKE API endpoint. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **api_endpoint_subnet_id**: The subnet for the OKE API endpoint. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **services_subnet_id**: (Optional) The subnet for the cluster service. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **encryption**: (Optional) Encryption settings.
+ - **kube_secret_kms_key_id**: (Optional) The KMS key to assign as the master encryption key for kube secrets. *default_kube_secret_kms_key_id* is used if undefined. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *kms_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **image_signing**: (Optional) image signing encryption settings
+ - **image_policy_enabled**: (Optional) whether the image verification policy is enabled. Default is false.
+ - **img_kms_key_id**: (Optional) the KMS key to assign as the *signing* key for images. *default_img_kms_key_id* is used if this is not defined. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *kms_dependency* variable. See [External Dependencies](#ext-dep) for details.
+
+### Workers
+Workers are managed using the **workers_configuration** object. It contains a set of attributes starting with the prefix **default_** and two attributes named **node_pools** and **virtual_node_pools**. The **default_** attribute values are applied to all node pools and some of them to all virtual node pools.
+The defined **default_** attributes are the following:
+
+- **default_compartment_id**: (Optional) The default compartment for all node pools and virtual node pools. It can be overridden by *compartment_id* attribute in each node pool or virtual pool. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_kms_key_id**: (Optional) The default encryption key for nodes in node pools. It can be overridden by *kms_key_id* attribute in each unit. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *kms_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **default_cis_level**: (Optional) The default CIS OCI Benchmark profile level for all node pools. Level "2" enforces usage of customer managed keys for encryption. Default is "1". It can be overridden by *cis_level* attribute in each unit.
+- **default_defined_tags**: (Optional) The default defined tags for all node pools and virtual node pools. It can be overridden by *defined_tags* attribute in each unit.
+- **default_freeform_tags**: (Optional) the default freeform tags for all node pools and virtual node pools. It can be overridden by *freeform_tags* attribute in each unit.
+- **default_ssh_public_key_path**: (Optional) The default SSH public key path used to access all nodes. It can be overridden by the *ssh_public_key* attribute in each node pool.
+- **default_initial_node_labels**: (Optional) The default initial node labels for all node pools and virtual node pools, a list of key/value pairs to add to nodes after they join the OKE cluster.
+
+#### Node Pools
+Node Pools are defined using the optional **node_pools** attribute. In Terraform terms, it is a map of objects, where each object is referred by an identifying key. The following attributes are supported:
+- **cis_level**: (Optional) The CIS OCI Benchmark profile level to apply. The *default_cis_level* is used if undefined.
+- **kubernetes_version**: (Optional) The Kubernetes version for the node pool. it cannot be two versions older or newer than the cluster version. If not specified, the version of the cluster is selected.
+- **cluster_id**: The cluster where the node pool is created. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to a cluster from the **clusters_configuration**.
+- **compartment_id**: (Optional) The compartment where the node pool is created. If the cluster and the node pools are both managed by this module, attributes **compartment_id** and **default_compartment_id** are ignored, as the compartment for the node pool is taken from the cluster assigned to the node pool in the *cluster_id* attribute. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **name**: The node pool display name.
+- **defined_tags**: (Optional) The node pool defined_tags. *default_defined_tags* is used if undefined.
+- **freeform_tags**: (Optional) The node pool freeform_tags. *default_freeform_tags* is used if undefined.
+- **initial_node_labels**: (Optional) A list of key/value pairs to add to nodes after they join the OKE cluster.
+- **size**: (Optional) The number of nodes in the node pool.
+- **networking**: Node pool networking settings.
+ - **workers_nsg_ids**: (Optional) The NSGs where nodes are placed in. This attribute is overloaded. It can be assigned either literal OCIDs or references (keys) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **workers_subnet_id**: The nodes subnet. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **pods_subnet_id**: (Optional) The pods subnet. **Applicable to native CNI only**. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **pods_nsg_ids**: (Optional) The NSGs where pods are placed in. **Applicable to native CNI only**. This attribute is overloaded. It can be assigned either literal OCIDs or references (keys) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **max_pods_per_node**: (Optional) The maximum number of pods per node. **Applicable to native CNI only**.
+
+- **node_config_details**: The configuration of nodes in the node pool.
+ - **ssh_public_key_path**: (Optional) The SSH public key path used to access the workers. *default_ssh_public_key_path* is used if undefined.
+ - **defined_tags**: (Optional) The nodes defined_tags. *default_defined_tags* is used if undefined.
+ - **freeform_tags**: (Optional) The nodes freeform_tags. *default_freeform_tags* is used if undefined.
+ - **image**: (Optional) The nodes image. It can be specified as an OCID or as an Oracle Linux Version. Example: "8.8". If not specified the latest Oracle Linux image is selected.
+ - **node_shape**: The shape of the nodes.
+ - **capacity_reservation_id**: (Optional) The OCID of the compute capacity reservation in which to place the nodes.
+ - **flex_shape_settings**: (Optional) Flex shape settings.
+ - **memory**: (Optional) The amount of memory for Flex shapes. Default is 16GB.
+ - **ocpus**: (Optional) The number of OCPUs for Flex shapes. Default is 1.
+ - **boot_volume**: (Optional) The boot volume settings.
+ - **size**: (Optional) The boot volume size. Default is 60.
+ - **preserve_boot_volume**: (Optional) Whether to preserve the boot volume when nodes are terminated.
+ - **encryption**: (Optional) The encryption settings.
+ - **enable_encrypt_in_transit**: (Optional) Whether to enable in-transit encryption. Default is false.
+ - **kms_key_id**: (Optional) The KMS key to assign as the master encryption key. *default_kms_key_id* is used if undefined.
+ - **placement**: (Optional) Placement settings.
+ - **availability_domain**: (Optional) The nodes availability domain. Default is 1.
+ - **fault_domain**: (Optional) The nodes fault domain. Default is 1.
+ - **node_eviction**: (Optional) Nodes eviction settings.
+ - **grace_duration**: (Optional) The duration in seconds after which OKE gives up on pods eviction on the node. Default is 3600 seconds.
+ - **force_delete**: (Optional) Whether the nodes should be deleted if all pods are not evicted during the grace period.
+ - **node_cycling**: (Optional) Nodes cycling settings. **Applicable to enhanced clusters only**.
+ - **enable_cycling**: (Optional) Whether node cycling is enabled. Default is false.
+ - **max_surge**: (Optional) The maximum number of additional new compute instances that are temporarily created and added to node pool during the cycling process. OKE supports both integer and percentage input. Default is 1. It ranges from 0 up to node pool size or between 0% to 100%.
+ - **max_unavailable**: (Optional) The maximum number of active nodes that are terminated from node pool during the cycling process. OKE supports both integer and percentage input. Default is 0. It ranges from 0 up to node pool size or between 0% to 100%.
+
+#### Virtual Node Pools
+Virtual Node Pools are defined using the optional **virtual_node_pools** attribute. In Terraform terms, it is a map of objects, where each object is referred by an identifying key. The following attributes are supported:
+- **cluster_id**: The cluster where the virtual node pool is created. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to a cluster from the **clusters_configuration**.
+- **compartment_id**: (Optional) The compartment where the virtual node pool is created. If the cluster and the virtual node pools are both managed by this module, the attributes **compartment_id** and **default_compartment_id** are ignored, as the compartment for the virtual node pool is taken from the cluster assigned to the virtual node pool in the **cluster_id** attribute. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *compartments_dependency* variable. See [External Dependencies](#ext-dep) for details.
+- **name**: The virtual node pool display name.
+- **defined_tags**: (Optional) The virtual node pool defined_tags. *default_defined_tags* is used if undefined.
+- **freeform_tags**: (Optional) The virtual node pool freeform_tags. *default_freeform_tags* is used if undefined.
+- **virtual_nodes_defined_tags**: (Optional) The defined_tags that apply to virtual nodes. *default_defined_tags* is used if undefined.
+- **virtual_nodes_freeform_tags**: (Optional) The freeform_tags that apply to virtual nodes. *default_freeform_tags* is used if undefined.
+- **initial_node_labels**: (Optional) A list of key/value pairs to add to virtual nodes when they join the OKE cluster.
+- **size**: (Optional) The number of nodes in the virtual node pool.
+- **pod_shape**: The pods shape. At the time this Terraform code was created, the shapes available are: "Pod.Standard.A1.Flex", "Pod.Standard.E3.Flex", "Pod.Standard.E4.Flex".
+- **networking**: The virtual node pool networking settings.
+ - **workers_nsg_ids**: (Optional) The NSGs where the virtual nodes are placed. This attribute is overloaded. It can be assigned either literal OCIDs or references (keys) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **workers_subnet_id**: The virtual nodes subnet. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **pods_subnet_id**: (Optional) the pods subnet. This attribute is overloaded. It can be assigned either a literal OCID or a reference (a key) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **pods_nsg_ids**: (Optional) The NSGs where the pods are placed. This attribute is overloaded. It can be assigned either literal OCIDs or references (keys) to an OCID in *network_dependency* variable. See [External Dependencies](#ext-dep) for details.
+ - **placement**: (Optional) The placement settings.
+ - **availability_domain**: (Optional) The virtual nodes availability domain. Default is 1.
+ - **fault_domain**: (Optional) The virtual nodes fault domain. Default is 1.
+ - **taints**: (Optional) Taints enable virtual nodes to repel pods, thereby ensuring that pods do not run on virtual nodes in a particular virtual node pool. Taints work together with Kubernetes tolerations to ensure that pods are not scheduled in undesired nodes.
+ - **effect**: (Optional) The taint effect. Valid values are "NoSchedule", "NoExecute", or "PreferNoSchedule".
+ - **key**: (Optional) The node label key to apply the taint to.
+ - **value**: (Optional) The node label value to apply the taint to.
+
+
+### External Dependencies
+An optional feature, external dependencies are resources managed elsewhere that resources managed by this module may depend on. The following dependencies are supported:
+- **compartments_dependency**: A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an *id* attribute with the compartment OCID.
+
+Example:
+```
+{
+ "APP-CMP": {
+ "id": "ocid1.compartment.oc1..aaaaaaaa...7xq"
+ }
+}
+```
+- **network_dependency**: A map of objects containing the externally managed network resources (including subnets and network security groups) this module may depend on. All map objects must have the same type and should contain the following attributes:
+ - An *id* attribute with the VCN OCID.
+ - An *id* attribute with the subnet OCID.
+ - An *id* attribute with the network security group OCID.
+
+Example:
+```
+{
+ "vcns" : {
+ "OKE-VCN" : {
+ "id" : "ocid1.vcn.oc1.iad.aaaaaaaax...t6h"
+ }
+ },
+ "subnets" : {
+ "APP-SUBNET" : {
+ "id" : "ocid1.subnet.oc1.iad.aaaaaaaax...e7a"
+ }
+ },
+ "network_security_groups" : {
+ "APP-NSG" : {
+ "id" : "ocid1.networksecuritygroup.oc1.iad.aaaaaaaa...xlq"
+ }
+ }
+}
+```
+- **kms_dependency**: A map of objects containing the externally managed encryption keys this module may depend on. All map objects must have the same type and must contain at least an *id* attribute with the encryption key OCID.
+
+Example:
+```
+{
+ "APP-KEY": {
+ "id": "ocid1.key.oc1.iad.ejsppeqvaafyi.abuwcl...yna"
+ }
+}
+```
+
+## Related Documentation
+- [OKE](https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengoverview.htm)
+
+
+## Known Issues
+
+### Node pool
+1. When updating the *node_cycling* attribute, if you are changing anything else to node_config_details, you will get the following error:
+
+```
+ Error: 409-Conflict, Cannot perform nodepool cycling and nodepool Placement Configuration change simultaneously.
+│ Suggestion: The resource is in a conflicted state. Please retry again or contact support for help with service: Containerengine Node Pool
+│ Documentation: https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/containerengine_node_pool
+│ API Reference: https://docs.oracle.com/iaas/api/#/en/containerengine/20180222/NodePool/UpdateNodePool
+│ Request Target: PUT https://containerengine.eu-frankfurt-1.oci.oraclecloud.com/20180222/nodePools/ocid1.nodepool.oc1.eu-frankfurt-1.aaaaaaaa5gyeinkioj74eobjxv5rryn24bwkxp2k4zx6ks53nnx6l53eazza
+│ Provider version: 5.16.0, released on 2023-10-11. This provider is 10 Update(s) behind to current.
+│ Service: Containerengine Node Pool
+│ Operation Name: UpdateNodePool
+│ OPC request ID: 59bbfd0704eff01d226851aa8adba0b2/D3D0C22D125AAB7680601414509B46D8/71438074CF7D178285DD4AE5A9E82632
+│
+│
+│ with module.oke.oci_containerengine_node_pool.these["pool1"],
+│ on ../../nodepool.tf line 30, in resource "oci_containerengine_node_pool" "these":
+│ 30: resource "oci_containerengine_node_pool" "these"
+```
+
+2. When the *image* attribute is not specified, the most recent available image is selected. This means OKE selects the most recent image at every run, hence modifying the node pool. However, the new image is available only for the newly created/recreated nodes in the pool.
+
+### Virtual Pool
+Some of the features available for node pools are not supported in virtual node pools. For a detailed list, check the [documentation](https://docs.public.oneportal.content.oci.oraclecloud.com/en-us/iaas/Content/ContEng/Tasks/contengcomparingvirtualwithmanagednodes_topic.htm).
+Some examples:
+1. Flannel and other third party CNI plugins are not supported. Virtual nodes only supported the OCI VCN-Native Pod Networking CNI plugin.
+2. Persistent volume claims (PVCs) are not supported.
+4. Network providers that support NetworkPolicy resources alongside the CNI plugin used in the cluster (such as Calico and Cilium) are not supported.
\ No newline at end of file
diff --git a/cis-oke/SPEC.MD b/cis-oke/SPEC.MD
new file mode 100644
index 0000000..36526a8
--- /dev/null
+++ b/cis-oke/SPEC.MD
@@ -0,0 +1,49 @@
+## Requirements
+
+No requirements.
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [oci](#provider\_oci) | n/a |
+
+## Modules
+
+No modules.
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [oci_containerengine_cluster.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/containerengine_cluster) | resource |
+| [oci_containerengine_node_pool.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/containerengine_node_pool) | resource |
+| [oci_containerengine_virtual_node_pool.these](https://registry.terraform.io/providers/oracle/oci/latest/docs/resources/containerengine_virtual_node_pool) | resource |
+| [oci_containerengine_cluster_option.cluster_options](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/containerengine_cluster_option) | data source |
+| [oci_containerengine_cluster_option.kube_versions](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/containerengine_cluster_option) | data source |
+| [oci_containerengine_clusters.existing](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/containerengine_clusters) | data source |
+| [oci_containerengine_clusters.vpool](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/containerengine_clusters) | data source |
+| [oci_containerengine_node_pool_option.np_option](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/containerengine_node_pool_option) | data source |
+| [oci_core_subnet.subnet](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/core_subnet) | data source |
+| [oci_identity_availability_domains.ads](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_availability_domains) | data source |
+| [oci_identity_availability_domains.vpool_ads](https://registry.terraform.io/providers/oracle/oci/latest/docs/data-sources/identity_availability_domains) | data source |
+
+## Inputs
+
+| Name | Description | Type | Default | Required |
+|------|-------------|------|---------|:--------:|
+| [clusters\_configuration](#input\_clusters\_configuration) | Cluster configuration attributes. | object({
default_compartment_id = optional(string), # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
default_img_kms_key_id = optional(string) # the default KMS key to assign as the master encryption key for images. It's overriden by the img_kms_key_id attribute within each object.
default_kube_secret_kms_key_id = optional(string) # the default KMS key to assign as the master encryption key for kubernetes secrets. It's overriden by the kube_secret_kms_key_id attribute within each object.
default_cis_level = optional(string, "1") # The CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
clusters = map(object({ # the clusters to manage in this configuration.
cis_level = optional(string, "1")
compartment_id = optional(string) # the compartment where the cluster is created. default_compartment_ocid is used if this is not defined.
kubernetes_version = optional(string) # the kubernetes version. If not specified the latest version will be selected.
name = string # the cluster display name.
is_enhanced = optional(bool, false) # if the cluster is enhanced. It is designed to work only on Native CNI. Default is false.
cni_type = optional(string, "flannel") # the CNI type of the cluster. Can be either "flannel" or "native". Default is "flannel".
defined_tags = optional(map(string)) # clusters defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # clusters freeform_tags. default_freeform_tags is used if this is not defined.
options = optional(object({ # optional attributes for the cluster.
add_ons = optional(object({ # configurable cluster addons.
dashboard_enabled = optional(bool, false) # if the dashboard is enabled. Default to false.
tiller_enabled = optional(bool, false) # if the tiller is enabled. Default to false.
}))
admission_controller = optional(object({ # configurable cluster admission controllers.
pod_policy_enabled = optional(bool, false) # if the pod policy is enabled. Default to false.
}))
kubernetes_network_config = optional(object({ # pods and services network configuration for kubernetes.
pods_cidr = optional(string) # the CIDR block for Kubernetes pods. Optional, defaults to 10.244.0.0/16.
services_cidr = optional(string) # the CIDR block for Kubernetes services. Optional, defaults to 10.96.0.0/16.
}))
persistent_volume_config = optional(object({ # configuration to be applied to block volumes created by Kubernetes Persistent Volume Claims (PVC).
defined_tags = optional(map(string)) # PVC defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # PVC freeform_tags. default_freeform_tags is used if this is not defined.
}))
service_lb_config = optional(object({ # configuration to be applied to load balancers created by Kubernetes services
defined_tags = optional(map(string)) # LB defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # LB freeform_tags. default_freeform_tags is used if this is not defined.
}))
}))
networking = object({ # cluster networking settings.
vcn_id = string # the vcn where the cluster will be created.
is_api_endpoint_public = optional(bool) # if the api endpoint is public. default to false.
api_endpoint_nsg_ids = optional(list(string)) # the nsgs used by the api endpoint.
api_endpoint_subnet_id = string # the subnet for the api endpoint.
services_subnet_id = optional(list(string)) # the subnets for the services(Load Balancers).
})
encryption = optional(object({ # encryption settings
kube_secret_kms_key_id = optional(string) # # the KMS key to assign as the master encryption key for kube secrets. default_kube_secret_kms_key_id is used if this is not defined.
}))
image_signing = optional(object({
image_policy_enabled = optional(bool) # whether the image verification policy is enabled. default to false.
img_kms_key_id = optional(string) # the KMS key to assign as the master encryption key for images. default_img_kms_key_id is used if this is not defined.
}))
}))
})
| `null` | no |
+| [compartments\_dependency](#input\_compartments\_dependency) | A map of objects containing the externally managed compartments this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the compartment OCID) of string type. | `map(any)` | `null` | no |
+| [enable\_output](#input\_enable\_output) | Whether Terraform should enable the module output. | `bool` | `true` | no |
+| [kms\_dependency](#input\_kms\_dependency) | A map of objects containing the externally managed encryption keys this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the key OCID) of string type. | `map(any)` | `null` | no |
+| [module\_name](#input\_module\_name) | The module name. | `string` | `"cis-oke"` | no |
+| [network\_dependency](#input\_network\_dependency) | A map of objects containing the externally managed network resources this module may depend on. All map objects must have the same type and must contain at least an 'id' attribute (representing the network resource OCID) of string type. | `map(any)` | `null` | no |
+| [workers\_configuration](#input\_workers\_configuration) | Worker Nodes configuration attributes | object({
default_cis_level = optional(string, "1") # the CIS OCI Benchmark profile level. Level "1" is be practical and prudent. Level "2" is intended for environments where security is more critical than manageability and usability. Default is "1".
default_compartment_id = optional(string) # the default compartment where all resources are defined. It's overriden by the compartment_ocid attribute within each object.
default_defined_tags = optional(map(string)), # the default defined tags. It's overriden by the defined_tags attribute within each object.
default_freeform_tags = optional(map(string)), # the default freeform tags. It's overriden by the freeform_tags attribute within each object.
default_ssh_public_key_path = optional(string) # the default SSH public key path used to access the workers.
default_kms_key_id = optional(string) # the default KMS key to assign as the master encryption key. It's overriden by the kms_key_id attribute within each object.
default_initial_node_labels = optional(map(string)) # the default initial node labels, a list of key/value pairs to add to nodes after they join the Kubernetes cluster.
node_pools = optional(map(object({ # the node pools to manage in this configuration.
cis_level = optional(string, "1")
kubernetes_version = optional(string) # the kubernetes version for the node pool. it cannot be 2 versions older behind of the cluster version or newer. If not specified, the version of the cluster will be selected.
cluster_id = string # the cluster where the node pool will be created.
compartment_id = optional(string) # the compartment where the node pool is created. default_compartment_ocid is used if this is not defined.
name = string # the node pool display name.
defined_tags = optional(map(string)) # node pool defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # node pool freeform_tags. default_freeform_tags is used if this is not defined.
initial_node_labels = optional(map(string)) # a list of key/value pairs to add to nodes after they join the Kubernetes cluster.
size = optional(number) # the number of nodes that should be in the node pool.
networking = object({ # node pool networking settings.
workers_nsg_ids = optional(list(string)) # the nsgs to be used by the nodes.
workers_subnet_id = string # the subnet for the nodes.
pods_subnet_id = optional(string) # the subnet for the pods. only applied to native CNI.
pods_nsg_ids = optional(list(string)) # the nsgs to be used by the pods. only applied to native CNI.
max_pods_per_node = optional(number) # the maximum number of pods per node. only applied to native CNI.
})
node_config_details = object({ # the configuration of nodes in the node pool.
ssh_public_key_path = optional(string) # the SSH public key path used to access the workers. if not specified default_ssh_public_key_path will be used.
defined_tags = optional(map(string)) # nodes defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # nodes freeform_tags. default_freeform_tags is used if this is not defined.
image = optional(string) # the image for the nodes. Can be specified as ocid or as an Oracle Linux Version. Example: "8.8". If not specified the latest Oracle Linux image will be selected.
node_shape = string # the shape of the nodes.
capacity_reservation_id = optional(string) # the OCID of the compute capacity reservation in which to place the compute instance.
flex_shape_settings = optional(object({ # flex shape settings
memory = optional(number, 16) # the nodes memory for Flex shapes. Default is 16GB.
ocpus = optional(number, 1) # the nodes ocpus number for Flex shapes. Default is 1.
}))
boot_volume = optional(object({ # the boot volume settings.
size = optional(number, 60) # the boot volume size.Default is 60.
preserve_boot_volume = optional(bool, false) # whether to preserve the boot volume after the nodes are terminated.
}))
encryption = optional(object({ # the encryption settings.
enable_encrypt_in_transit = optional(bool) # whether to enable the encrypt in transit. Default is false.
kms_key_id = optional(string) # the KMS key to assign as the master encryption key. default_kms_key_id is used if this is not defined.
}))
placement = optional(list(object({ # placement settings.
availability_domain = optional(number) # the nodes availability domain. Default is 1.
fault_domain = optional(number) # the nodes fault domain. Default is 1.
})))
node_eviction = optional(object({ # node eviction settings.
grace_duration = optional(number) # duration after which OKE will give up eviction of the pods on the node. Can be specified in seconds. Default is 60 minutes.
force_delete = optional(bool) # whether the nodes should be deleted if you cannot evict all the pods in grace period.
}))
node_cycling = optional(object({ # node cycling settings. Available only for Enhanced clusters.
enable_cycling = optional(bool) # whether to enable node cycling. Default is false.
max_surge = optional(string) # maximum additional new compute instances that would be temporarily created and added to nodepool during the cycling nodepool process. OKE supports both integer and percentage input. Defaults to 1, Ranges from 0 to Nodepool size or 0% to 100%.
max_unavailable = optional(string) # maximum active nodes that would be terminated from nodepool during the cycling nodepool process. OKE supports both integer and percentage input. Defaults to 0, Ranges from 0 to Nodepool size or 0% to 100%.
}))
})
})), {})
virtual_node_pools = optional(map(object({
cluster_id = string # the cluster where the virtual node pool will be created.
compartment_id = optional(string) # the compartment where the virtual node pool is created. default_compartment_ocid is used if this is not defined.
name = string # the virtual node pool display name.
defined_tags = optional(map(string)) # virtual node pool defined_tags. default_defined_tags is used if this is not defined.
freeform_tags = optional(map(string)) # virtual node pool freeform_tags. default_freeform_tags is used if this is not defined.
virtual_nodes_defined_tags = optional(map(string)) # defined_tags that apply to virtual nodes. default_defined_tags is used if this is not defined.
virtual_nodes_freeform_tags = optional(map(string)) # freeform_tags that apply to virtual nodes. default_freeform_tags is used if this is not defined.
initial_node_labels = optional(map(string)) # a list of key/value pairs to add to virtual nodes after they join the Kubernetes cluster.
size = optional(number) # the number of virtual nodes that should be in the virtual node pool.
pod_shape = string # the shape assigned to pods. It can be one of Pod.Standard.A1.Flex, Pod.Standard.E3.Flex, Pod.Standard.E4.Flex.
networking = object({ # virtual node pool networking settings.
workers_nsg_ids = optional(list(string)) # the nsgs to be used by the virtual nodes.
workers_subnet_id = string # the subnet for the virtual nodes.
pods_subnet_id = string # the subnet for the pods.
pods_nsg_ids = optional(list(string)) # the nsgs to be used by the pods.
})
placement = optional(list(object({ # placement settings.
availability_domain = optional(number) # the virtual nodes availability domain. Default is 1.
fault_domain = optional(number) # the virtual nodes fault domain. Default is 1.
})))
taints = optional(list(object({ # the taints will be applied to the Virtual Nodes for Kubernetes scheduling.
effect = optional(string) # the effect of the pair.
key = optional(string) # the key of the pair.
value = optional(string) # the value of the pair.
})))
})), {})
})
| `null` | no |
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [clusters](#output\_clusters) | The Kubernetes Clusters |
+| [node\_pools](#output\_node\_pools) | The OKE Node Pools |
+| [virtual\_node\_pools](#output\_virtual\_node\_pools) | The OKE Virtual Node Pools |
diff --git a/cis-oke/examples/flannel/basic-access-from-localhost/README.md b/cis-oke/examples/flannel/basic-access-from-localhost/README.md
new file mode 100644
index 0000000..91583cc
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-localhost/README.md
@@ -0,0 +1,86 @@
+# OKE Flannel with Localhost Access Example
+
+## Introduction
+
+This example shows how to deploy OKE clusters and node pools in OCI using the [cis-oke module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke). It deploys one Flannel-based basic OKE Cluster, one node pool, one Bastion service endpoint and one Bastion session for cluster management with the characteristics described below.
+
+Once the cluster is provisioned, cluster access is automatically enabled from localhost via the OCI Bastion service endpoint.
+
+### Pre-Requisite
+
+The OKE cluster and the Node Pool depend on a pre existing Virtual Cloud Network (VCN). A VCN built specifically for this deployment is available in [flannel network example](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-networking/tree/main/examples/oke-examples/flannel).
+
+### Resources Deployed by this Example
+
+OKE cluster (OKE1):
+- of *basic* type;
+- set with the latest Kubernetes version;
+- with Flannel CNI;
+- with a private API endpoint.
+
+Node pool (NODEPOOL1):
+- created in the same compartment as the cluster;
+- with the same Kubernetes version as the cluster;
+- with one worker node (it is set by *workers_configuration.node_pools.NODEPOOL1.size* attribute);
+- node has the "VM.Standard.E4.Flex" shape;
+- node has 16 GB memory and 1 OCPU by default;
+- node boot volume size is 60GB and is terminated when the node is destroyed.
+
+Bastion service (BASTION-1):
+- of *standard* type.
+
+Bastion session (SESSION-1):
+- of **PORT_FORWARDING** type, allowing port forwarding to the OKE API endpoint;
+- targeting the OKE1 cluster API endpoint on port 6443.
+
+See [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+## Using this Example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-oke module README.md](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke/README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
+
+## Accessing the Cluster
+
+Managing Kubernetes applications in OCI includes the ability to invoke OKE API endpoint and SSH'ing into Worker nodes.
+Invoking the OKE API endpoint and accessing Worker nodes differs depending on whether they are in a private or public subnet. This example assumes the API endpoint and Worker nodes are in private subnets and are invoked/accessed via an OCI Bastion Service endpoint that is deployed in the Access subnet, which is also private.
+
+### Accessing OKE API Endpoint
+
+The code automatically creates a *kubeconfig* file in the Terraform configuration folder, required for accessing the OKE API endpoint.
+
+To connect to the OKE API endpoint, in a terminal, execute the command provided in the **sessions** output, that would look like:
+```
+ssh -i ~/.ssh/id_rsa -N -L 6443:10.0.x.x:6443 -p 22 ocid1.bastionsession.oc1...@host.bastion.eu-frankfurt-1.oci.oraclecloud.com
+```
+
+Following that, in another terminal, set the KUBECONFIG environment variable to the *kubeconfig* file that was created in the Terraform configuration folder.
+```
+export KUBECONFIG =
+```
+
+You are now all set to use *kubectl* tool to manage your OKE applications. As an example, you can try deploying a sample application, checking and deleting it:
+```
+> kubectl create -f https://k8s.io/examples/application/deployment.yaml
+> kubectl get deployments
+> kubectl delete -f https://k8s.io/examples/application/deployment.yaml
+```
+
+### Connecting to Worker Nodes with SSH
+
+1. Using the Console, enable the Cloud Agent Bastion plugin in the worker node.
+2. Using the Console, create a managed SSH session for the worker node in the provisioned OCI Bastion service.
+3. Connect to worker node using the SSH command provided for the managed SSH session. The command looks like:
+```
+ssh -o ProxyCommand="ssh -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXXX@host.bastion.us-phoenix-1.oci.oraclecloud.com" -p 22 opc@
+```
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-localhost/input.auto.tfvars.template b/cis-oke/examples/flannel/basic-access-from-localhost/input.auto.tfvars.template
new file mode 100644
index 0000000..e2afe3a
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-localhost/input.auto.tfvars.template
@@ -0,0 +1,84 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+# tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+# user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+# fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+# private_key_path = "" # This is the full path on your local system to the API signing private key.
+# private_key_password = "" # This is the password that protects the private key, if any.
+# region = "" # The region name.
+
+
+#---------------------------------------
+# Input variable
+#---------------------------------------
+
+clusters_configuration = {
+ default_compartment_id = ""
+ clusters = {
+ OKE1 = {
+ name = "oke-flannel-cluster"
+ networking = {
+ vcn_id = ""
+ api_endpoint_subnet_id = ""
+ services_subnet_id = [""]
+ api_endpoint_nsg_ids = [""]
+ }
+ }
+ }
+}
+
+workers_configuration = {
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ node_pools = {
+ NODEPOOL1 = {
+ cluster_id = "OKE1"
+ name = "node-pool"
+ size = 1
+ networking = {
+ workers_subnet_id = ""
+ workers_nsg_ids = [""]
+ }
+ node_config_details = {
+ node_shape = "VM.Standard.E4.Flex"
+ }
+ }
+ }
+}
+
+bastions_configuration = {
+ bastions = {
+ BASTION-1 = {
+ bastion_type = "STANDARD"
+ compartment_id = ""
+ subnet_id = ""
+ cidr_block_allow_list = [""] # Try to be as much specific as possible, and avoid entering "0.0.0.0/0".
+ name = "OkeFlannelBastionByTerraform"
+ }
+ }
+}
+
+sessions_configuration = {
+ sessions = {
+ PORT-FORWARDING-SESSION = {
+ bastion_id = "BASTION-1"
+ ssh_public_key = ""
+ session_type = "PORT_FORWARDING"
+ target_resource = "OKE1"
+ target_port = "6443"
+ session_name = "PortForwardingByTerraform"
+ }
+ }
+}
+
+ssh_private_key = "" # Used for generating the ssh command for port forwarding. The private key contents aren't sent anywhere.
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-localhost/main.tf b/cis-oke/examples/flannel/basic-access-from-localhost/main.tf
new file mode 100644
index 0000000..c816a93
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-localhost/main.tf
@@ -0,0 +1,27 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+module "oke" {
+ source = "../../../"
+ clusters_configuration = var.clusters_configuration
+ workers_configuration = var.workers_configuration
+}
+
+module "bastion" {
+ source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security.git//bastion?ref=v0.1.4"
+ bastions_configuration = var.bastions_configuration
+ sessions_configuration = var.sessions_configuration
+ endpoints_dependency = {for k, v in module.oke.clusters : k => {"ip_address" : split(":",v.endpoints[0].private_endpoint)[0]}}
+}
+
+data "oci_containerengine_cluster_kube_config" "kube_config" {
+ for_each = var.clusters_configuration != null ? var.clusters_configuration["clusters"] : {}
+ cluster_id = module.oke.clusters[each.key].id
+ token_version = "2.0.0"
+}
+
+resource "local_file" "kubeconfig" {
+ for_each = var.clusters_configuration != null ? var.clusters_configuration["clusters"] : {}
+ content = "${tostring(replace(data.oci_containerengine_cluster_kube_config.kube_config[each.key].content, split(":", module.oke.clusters[each.key].endpoints[0].private_endpoint)[0], "127.0.0.1"))}"
+ filename = "./kubeconfig"
+}
diff --git a/cis-oke/examples/flannel/basic-access-from-localhost/outputs.tf b/cis-oke/examples/flannel/basic-access-from-localhost/outputs.tf
new file mode 100644
index 0000000..f437c7f
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-localhost/outputs.tf
@@ -0,0 +1,16 @@
+
+# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+
+output "clusters" {
+ value = module.oke.clusters
+}
+
+output "node_pools" {
+ value = module.oke.node_pools
+}
+
+output "sessions" {
+ value = {for k, v in module.bastion.sessions : k => replace(replace(replace(v, "\"", "'"), "", var.ssh_private_key), "", "6443")}
+}
diff --git a/cis-oke/examples/flannel/basic-access-from-localhost/providers.tf b/cis-oke/examples/flannel/basic-access-from-localhost/providers.tf
new file mode 100644
index 0000000..4bd8b69
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-localhost/providers.tf
@@ -0,0 +1,20 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+ ignore_defined_tags = ["Oracle-Tags.CreatedBy", "Oracle-Tags.CreatedOn"]
+}
+
+terraform {
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+}
diff --git a/cis-oke/examples/flannel/basic-access-from-localhost/variables.tf b/cis-oke/examples/flannel/basic-access-from-localhost/variables.tf
new file mode 100644
index 0000000..3196284
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-localhost/variables.tf
@@ -0,0 +1,26 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+variable "tenancy_ocid" {}
+variable "region" { description = "Your tenancy region" }
+variable "user_ocid" { default = "" }
+variable "fingerprint" { default = "" }
+variable "private_key_path" { default = "" }
+variable "private_key_password" { default = "" }
+
+variable "clusters_configuration" {
+ type = any
+}
+variable "workers_configuration" {
+ type = any
+}
+variable "bastions_configuration" {
+ type = any
+}
+variable "sessions_configuration" {
+ type = any
+}
+variable "ssh_private_key" {
+ type = string
+ default = "~/.ssh/id_rsa"
+}
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/README.md b/cis-oke/examples/flannel/basic-access-from-operator-host/README.md
new file mode 100644
index 0000000..b022bcb
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/README.md
@@ -0,0 +1,134 @@
+# OKE Flannel with Operator Access Example
+
+## Introduction
+
+This example shows how to deploy OKE clusters and node pools in OCI using the [cis-oke module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke). It deploys one Flannel-based basic OKE Cluster, one node pool, one Bastion service endpoint, one Bastion session, and one Compute instance with the characteristics described below.
+
+Once the cluster is provisioned, cluster access is automatically enabled from the provisioned Compute instance, which is accessible via the OCI Bastion service endpoint. We refer to this Compute instance as the Operator host.
+
+### Pre-Requisites
+
+#### Networking
+The OKE cluster and the node pool depend on a pre existing Virtual Cloud Network (VCN). A VCN built specifically for this deployment is available in [flannel network example](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-networking/tree/main/examples/oke-examples/flannel).
+
+Additionally, the Operator host requires an instance principal credential properly authorized for managing the OKE cluster. That means a dynamic group and a policy are required.
+
+#### IAM Dynamic Group and Policy
+##### Dynamic Group Matching Rule
+```
+instance.compartment.id=''
+```
+
+##### Dynamic Group Policy
+```
+Allow dynamic-group to manage cluster-family in compartment
+```
+
+The deployment of these IAM resources are automated by the [OKE Operator Host IAM example](../oke-operator-host-iam/).
+
+
+### Resources Deployed by this Example
+
+OKE cluster (OKE1):
+- of *basic* type;
+- set with the latest Kubernetes version;
+- with Flannel CNI;
+- with a private API endpoint.
+
+Node pool (NODEPOOL1):
+- created in the same compartment as the cluster;
+- with the same Kubernetes version as the cluster;
+- with one worker node (it is set by *workers_configuration.node_pools.NODEPOOL1.size* attribute);
+- node has the "VM.Standard.E4.Flex" shape;
+- node has 16 GB memory and 1 OCPU by default;
+- node boot volume size is 60GB and is terminated when the node is destroyed.
+
+Compute instance (INSTANCE-1), a.k.a. Operator host:
+- based on "VM.Standard.E4.Flex" shape, as defined by the *shape* attribute.
+- based on the "Oracle-Linux-Cloud-Developer-8.7-2023.04.28-1" platform image, as defined by *image.id* attribute.
+ - Either use the [platform-images module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/platform-images) to find Platform images information based on a search filter or search for the region-specific image OCID in [All Image Families](https://docs.oracle.com/en-us/iaas/images/).
+- it does **not** have the boot volume preserved on termination, as defined by *boot_volume.preserve_on_instance_deletion* attribute.
+- the boot volume is set to be backed up per Oracle-managed *bronze* backup policy (enforced by the module by default).
+- the instance enables the Cloud Agent Bastion plugin, enabling it to accept SSH connections from OCI Bastion service.
+
+Bastion Service endpoint (BASTION-1):
+- created in the same subnet as the Operator host.
+
+Bastion session (SESSION-1):
+- of **MANAGED_SSH** type, allowing SSH connectivity to the Operator host.
+
+See [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+## Using this Example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-oke module README.md](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke/README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
+
+## Accessing the Cluster
+
+Managing Kubernetes applications in OCI includes the ability to invoke OKE API endpoint and SSH'ing into worker nodes.
+Invoking the OKE API endpoint and accessing worker nodes differs depending on whether they are in a private or public subnet. This example assumes the API endpoint and worker nodes are in private subnets and are invoked/accessed from the Operator host, which is reachable via the OCI Bastion service.
+
+The code automatically connects to the Operator host using the Bastion service session to configure the *kubeconfig* file, install *kubectl* tool and set the instance with instance principal authentication.
+
+For connecting to the Operator host, execute the command provided in the **sessions** output, that would look like:
+```
+ssh -i -o ProxyCommand='ssh -i -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXX@host.bastion.oci.oraclecloud.com' -p 22 opc@
+```
+
+### Accessing OKE API Endpoint
+
+One connected to the Operator host, use *kubectl* tool to manage your OKE applications. As an example, you can try deploying a sample application, checking and deleting it:
+```
+> kubectl create -f https://k8s.io/examples/application/deployment.yaml
+> kubectl get deployments
+> kubectl delete -f https://k8s.io/examples/application/deployment.yaml
+```
+
+If for some reason *kubectl* does not get installed, once connected to the host, execute the [install_kubectl.sh](./install_kubectl.sh) script manually.
+
+After installing *kubectl*, if you can't get access to the cluster, confirm there is a *config* file under *$HOME/.kube*. Otherwise, manually create *kubeconfig* file, by executing:
+```
+oci ce cluster create-kubeconfig --cluster-id --file $HOME/.kube/config --region --token-version 2.0.0 --kube-endpoint PRIVATE_ENDPOINT
+```
+**Note**: the command above can be obtained in OCI Console, navigating to the "Quick Start" link within the OKE cluster.
+
+### Connecting to Worker Nodes via SSH
+
+This is done from the Operator host:
+
+1. Make the SSH private key that matches the SSH public key in the worker node available in the Operator host. If the private key is available in your local machine, it can be copied to the Operator host like:
+```
+scp -J ocid1.bastionsession.XXXXXXXX@host.bastion.oci.oraclecloud.com opc@:
+```
+2. Connect to the Operator host using the SSH command in the **sessions** output:
+```
+ssh -i -o ProxyCommand='ssh -i -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXX@host.bastion.oci.oraclecloud.com' -p 22 opc@
+```
+3. Restrict permissions on the private SSH key:
+```
+chmod 600
+```
+4. Connect to the worker node via SSH:
+```
+ssh -i opc@
+```
+
+Optionally, you can manually create a managed SSH session for the worker node in the provisioned OCI Bastion service, bypassing the Operator host altogether.
+
+1. Using the Console, enable the Cloud Agent Bastion plugin in the worker node.
+2. Using the Console, create a managed SSH session for the worker node in the provisioned OCI Bastion service.
+3. Connect to worker node using the SSH command provided for the managed SSH session. The command looks like:
+```
+ssh -o ProxyCommand="ssh -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXXX@host.bastion.us-phoenix-1.oci.oraclecloud.com" -p 22 opc@
+```
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/input.auto.tfvars.template b/cis-oke/examples/flannel/basic-access-from-operator-host/input.auto.tfvars.template
new file mode 100644
index 0000000..5babac8
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/input.auto.tfvars.template
@@ -0,0 +1,117 @@
+# Copyright (c) 2024 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+# tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+# user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+# fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+# private_key_path = "" # This is the full path on your local system to the API signing private key.
+# private_key_password = "" # This is the password that protects the private key, if any.
+# region = "" # The region name.
+
+
+#---------------------------------------
+# Input variable
+#---------------------------------------
+
+clusters_configuration = {
+ default_compartment_id = ""
+ clusters = {
+ OKE1 = {
+ name = ""
+ networking = {
+ vcn_id = ""
+ api_endpoint_subnet_id = ""
+ services_subnet_id = [""]
+ api_endpoint_nsg_ids = [""]
+ }
+ }
+ }
+}
+
+workers_configuration = {
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ node_pools = {
+ NODEPOOL1 = {
+ cluster_id = "OKE1"
+ name = ""
+ size = 1
+ networking = {
+ workers_subnet_id = ""
+ workers_nsg_ids = [""]
+ }
+ node_config_details = {
+ node_shape = "VM.Standard.E4.Flex"
+ }
+ }
+ }
+}
+
+instances_configuration = {
+ default_compartment_id = ""
+ default_subnet_id = ""
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ instances = {
+ INSTANCE-1 = {
+ shape = "VM.Standard.E4.Flex"
+ name = "OKE operator instance"
+ placement = {
+ availability_domain = 1
+ fault_domain = 1
+ }
+ boot_volume = {
+ size = 120
+ preserve_on_instance_deletion = false
+ }
+ networking = {
+ hostname = "oke-operator-instance"
+ network_security_groups = [""]
+ }
+ image = {
+ id = "" # As an example, you can use "Oracle-Linux-Cloud-Developer-8.7-2023.04.28-1" platform image, but you need its OCID, that is region-specific. Either use the https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/platform-images to find platform images information based on a search filter or search for the region-specific image OCID in https://docs.oracle.com/en-us/iaas/images/.
+ }
+ cloud_agent = {
+ plugins = [
+ { name = "Bastion", enabled = true }
+ ]
+ }
+ }
+ }
+}
+
+bastions_configuration = {
+ bastions = {
+ BASTION-1 = {
+ bastion_type = "STANDARD"
+ compartment_id = ""
+ subnet_id = ""
+ cidr_block_allow_list = [""] # Try to be as much specific as possible, and avoid entering "0.0.0.0/0".
+ name = "OkeFlannelBastionByTerraform"
+ }
+ }
+}
+
+sessions_configuration = {
+ sessions = {
+ SESSION-1 = {
+ bastion_id = "BASTION-1"
+ ssh_public_key = ""
+ session_type = "MANAGED_SSH"
+ target_user = "opc"
+ target_resource = "INSTANCE-1"
+ target_port = "22"
+ session_name = "ManagedSSHByTerraform"
+ }
+ }
+}
+
+ssh_private_key = "" # Used for generating the command for managed ssh. The private key contents aren't sent anywhere.
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/install_kubectl.sh b/cis-oke/examples/flannel/basic-access-from-operator-host/install_kubectl.sh
new file mode 100644
index 0000000..fbe7a29
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/install_kubectl.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+# Copyright 2017, 2019, Oracle Corporation and/or affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl
+
+cat <> ~/.bashrc
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/main.tf b/cis-oke/examples/flannel/basic-access-from-operator-host/main.tf
new file mode 100644
index 0000000..d107ee8
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/main.tf
@@ -0,0 +1,53 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+module "oke" {
+ source = "../../../"
+ clusters_configuration = var.clusters_configuration
+ workers_configuration = var.workers_configuration
+}
+
+module "operator_instance" {
+ source = "github.com/oracle-quickstart/terraform-oci-secure-workloads//cis-compute-storage?ref=v0.1.3"
+ providers = {
+ oci = oci
+ oci.block_volumes_replication_region = oci
+ }
+ instances_configuration = var.instances_configuration
+}
+
+module "bastion" {
+ depends_on = [module.oke]
+ source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security.git//bastion?ref=v0.1.4"
+ bastions_configuration = var.bastions_configuration
+ sessions_configuration = var.sessions_configuration
+ instances_dependency = module.operator_instance.instances
+}
+
+data "oci_containerengine_cluster_kube_config" "kube_config" {
+ for_each = var.clusters_configuration != null ? var.clusters_configuration["clusters"] : {}
+ cluster_id = module.oke.clusters[each.key].id
+ token_version = "2.0.0"
+}
+
+resource "null_resource" "add_kubeconfig" { # This null resource is used to add the kube config on the Operator instance using the Bastion Session.
+ for_each = var.sessions_configuration["sessions"]
+ provisioner "local-exec" {
+ command = format("%s %s", replace(replace(replace(replace(module.bastion.sessions[each.key], "\"", "'"), "", var.ssh_private_key), "-o ProxyCommand", "-o StrictHostKeyChecking=no -o ProxyCommand"), "-W", "-o StrictHostKeyChecking=no -W"), "-y -x 'mkdir ~/.kube/'")
+
+ }
+ provisioner "local-exec" {
+ command = format("%s %s", replace(replace(replace(replace(module.bastion.sessions[each.key], "\"", "'"), "", var.ssh_private_key), "-o ProxyCommand", "-o StrictHostKeyChecking=no -o ProxyCommand"), "-W", "-o StrictHostKeyChecking=no -W"), "-y -x 'echo \"${join(",", [for cluster in data.oci_containerengine_cluster_kube_config.kube_config : tostring(cluster.content)])}\" >> ~/.kube/config'")
+ }
+}
+
+data "local_file" "existing" {
+ filename = "${path.module}/install_kubectl.sh"
+}
+
+resource "null_resource" "install_kubect" { # This null resource is used to install the kubectl and set the Operator instance OCI authentication to Instance Principal.
+ for_each = var.sessions_configuration["sessions"]
+ provisioner "local-exec" {
+ command = format("%s %s", replace(replace(replace(replace(module.bastion.sessions[each.key], "\"", "'"), "", var.ssh_private_key), "-o ProxyCommand", "-o StrictHostKeyChecking=no -o ProxyCommand"), "-W", "-o StrictHostKeyChecking=no -W"), "-y -x '${data.local_file.existing.content}'")
+ }
+}
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/outputs.tf b/cis-oke/examples/flannel/basic-access-from-operator-host/outputs.tf
new file mode 100644
index 0000000..f437c7f
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/outputs.tf
@@ -0,0 +1,16 @@
+
+# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+
+output "clusters" {
+ value = module.oke.clusters
+}
+
+output "node_pools" {
+ value = module.oke.node_pools
+}
+
+output "sessions" {
+ value = {for k, v in module.bastion.sessions : k => replace(replace(replace(v, "\"", "'"), "", var.ssh_private_key), "", "6443")}
+}
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/providers.tf b/cis-oke/examples/flannel/basic-access-from-operator-host/providers.tf
new file mode 100644
index 0000000..4bd8b69
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/providers.tf
@@ -0,0 +1,20 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+ ignore_defined_tags = ["Oracle-Tags.CreatedBy", "Oracle-Tags.CreatedOn"]
+}
+
+terraform {
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+}
diff --git a/cis-oke/examples/flannel/basic-access-from-operator-host/variables.tf b/cis-oke/examples/flannel/basic-access-from-operator-host/variables.tf
new file mode 100644
index 0000000..ec1be8f
--- /dev/null
+++ b/cis-oke/examples/flannel/basic-access-from-operator-host/variables.tf
@@ -0,0 +1,29 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+variable "tenancy_ocid" {}
+variable "region" { description = "Your tenancy region" }
+variable "user_ocid" { default = "" }
+variable "fingerprint" { default = "" }
+variable "private_key_path" { default = "" }
+variable "private_key_password" { default = "" }
+
+variable "clusters_configuration" {
+ type = any
+}
+variable "workers_configuration" {
+ type = any
+}
+variable "instances_configuration" {
+ type = any
+}
+variable "bastions_configuration" {
+ type = any
+}
+variable "sessions_configuration" {
+ type = any
+}
+variable "ssh_private_key" {
+ type = string
+ default = "~/.ssh/id_rsa"
+}
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic/README.md b/cis-oke/examples/flannel/basic/README.md
new file mode 100644
index 0000000..39c1898
--- /dev/null
+++ b/cis-oke/examples/flannel/basic/README.md
@@ -0,0 +1,61 @@
+# OKE Flannel Basic Example
+
+## Introduction
+
+This example shows how to deploy Kubernetes clusters and node pools in OCI using the [cis-oke module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke). It deploys Flannel-based basic OKE cluster and one node pool with the characteristics described below.
+
+This example provides no cluster access automation. Automating access to the cluster can be implemented with the [OCI Bastion service module](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security/tree/main/bastion). See the [available examples](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security/tree/main/bastion/examples).
+
+As alternatives to this example, the following examples are available with cluster access automation:
+ 1. [OKE Flannel with Access from Localhost](../basic-access-from-localhost/), where the OKE cluster is managed from a host external to OCI (like the user laptop).
+ 2. [OKE Flannel with Access from Operator Host](../basic-access-from-operator-host/), where the OKE cluster is managed from a Compute instance deployed in OCI.
+
+### Pre-Requisite
+
+The OKE cluster and the node pool depend on a pre existing Virtual Cloud Network (VCN). A VCN built specifically for this deployment is available in [flannel network example](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-networking/tree/main/examples/oke-examples/flannel).
+
+### Resources Deployed by this Example
+
+OKE cluster (OKE1):
+- of *basic* type;
+- set with the latest Kubernetes version;
+- with Flannel CNI;
+- with a private API endpoint.
+
+Node pool (NODEPOOL1):
+- created in the same compartment as the cluster;
+- with the same Kubernetes version as the cluster;
+- with one worker node (it is set by *workers_configuration.node_pools.NODEPOOL1.size* attribute);
+- node has the "VM.Standard.E4.Flex" shape;
+- node has 16 GB memory and 1 OCPU by default;
+- node boot volume size is 60GB and is terminated when the node is destroyed;
+
+See [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+## Using this Example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-oke module README.md](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke/README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
+
+## Accessing the Cluster
+
+Managing Kubernetes applications in OCI includes the ability to invoke OKE API endpoint and SSH'ing into worker nodes.
+As the endpoint and worker nodes are in private subnets, access can be enabled through the OCI Bastion service or via a jump host that is deployed in a public subnet.
+
+### Access via OCI Bastion Service
+- **OKE API endpoint**: Cluster access is enabled by configuring a *kubeconfig* file and setting up the OCI Bastion service endpoint with a Port Forwarding session. [More information](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengsettingupbastion.htm).
+- **Worker nodes**: SSH access to worker nodes (\*) is enabled by setting up OCI Bastion service endpoint with a Managed SSH session. [More information](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengsettingupbastion.htm).
+
+Utilize the [OCI Bastion service module](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security/tree/main/bastion) to automate OCI Bastion service provisioning.
+
+(\*) SSH access to worker nodes via the OCI Bastion service requires the Cloud Agent Bastion plugin enabled in the worker nodes.
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic/input.auto.tfvars.template b/cis-oke/examples/flannel/basic/input.auto.tfvars.template
new file mode 100644
index 0000000..bca015d
--- /dev/null
+++ b/cis-oke/examples/flannel/basic/input.auto.tfvars.template
@@ -0,0 +1,57 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+# tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+# user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+# fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+# private_key_path = "" # This is the full path on your local system to the API signing private key.
+# private_key_password = "" # This is the password that protects the private key, if any.
+# region = "" # The region name.
+
+
+#---------------------------------------
+# Input variable
+#---------------------------------------
+
+clusters_configuration = {
+ default_compartment_id = ""
+ clusters = {
+ OKE1 = {
+ name = "oke-flannel-cluster"
+ networking = {
+ vcn_id = ""
+ api_endpoint_subnet_id = ""
+ services_subnet_id = [""]
+ api_endpoint_nsg_ids = [""]
+ }
+ }
+ }
+}
+
+workers_configuration = {
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ node_pools = {
+ NODEPOOL1 = {
+ cluster_id = "OKE1"
+ name = "node-pool"
+ size = 1
+ networking = {
+ workers_subnet_id = ""
+ workers_nsg_ids = [""]
+ }
+ node_config_details = {
+ node_shape = "VM.Standard.E4.Flex"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/basic/main.tf b/cis-oke/examples/flannel/basic/main.tf
new file mode 100644
index 0000000..17c7d2a
--- /dev/null
+++ b/cis-oke/examples/flannel/basic/main.tf
@@ -0,0 +1,8 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+module "oke" {
+ source = "../../../"
+ clusters_configuration = var.clusters_configuration
+ workers_configuration = var.workers_configuration
+}
diff --git a/cis-oke/examples/flannel/basic/outputs.tf b/cis-oke/examples/flannel/basic/outputs.tf
new file mode 100644
index 0000000..4ec7c3b
--- /dev/null
+++ b/cis-oke/examples/flannel/basic/outputs.tf
@@ -0,0 +1,12 @@
+
+# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+
+output "clusters" {
+ value = module.oke.clusters
+}
+
+output "node_pools" {
+ value = module.oke.node_pools
+}
diff --git a/cis-oke/examples/flannel/basic/providers.tf b/cis-oke/examples/flannel/basic/providers.tf
new file mode 100644
index 0000000..4bd8b69
--- /dev/null
+++ b/cis-oke/examples/flannel/basic/providers.tf
@@ -0,0 +1,20 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+ ignore_defined_tags = ["Oracle-Tags.CreatedBy", "Oracle-Tags.CreatedOn"]
+}
+
+terraform {
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+}
diff --git a/cis-oke/examples/flannel/basic/variables.tf b/cis-oke/examples/flannel/basic/variables.tf
new file mode 100644
index 0000000..5f378ae
--- /dev/null
+++ b/cis-oke/examples/flannel/basic/variables.tf
@@ -0,0 +1,16 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+variable "tenancy_ocid" {}
+variable "region" { description = "Your tenancy region" }
+variable "user_ocid" { default = "" }
+variable "fingerprint" { default = "" }
+variable "private_key_path" { default = "" }
+variable "private_key_password" { default = "" }
+
+variable "clusters_configuration" {
+ type = any
+}
+variable "workers_configuration" {
+ type = any
+}
diff --git a/cis-oke/examples/flannel/oke-operator-host-iam/input.auto.tfvars.template b/cis-oke/examples/flannel/oke-operator-host-iam/input.auto.tfvars.template
new file mode 100644
index 0000000..289a9b3
--- /dev/null
+++ b/cis-oke/examples/flannel/oke-operator-host-iam/input.auto.tfvars.template
@@ -0,0 +1,46 @@
+# Copyright (c) 2024 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+# tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+# user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+# fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+# private_key_path = "" # This is the full path on your local system to the API signing private key.
+# private_key_password = "" # This is the password that protects the private key, if any.
+# home_region = ""# The home region name.
+
+#---------------------------------------
+# Input variables
+#---------------------------------------
+
+dynamic_groups_configuration = {
+ dynamic_groups = {
+ OKE-OPERATOR-DYN-GROUP : {
+ name : "oke-operator-dynamic-group",
+ description : "Dynamic group for OKE operator.",
+ matching_rule : "instance.compartment.id = ''"
+ }
+ }
+}
+
+policies_configuration = {
+ supplied_policies : {
+ "OKE-OPERATOR-POLICY" : {
+ name : "oke-operator-policy"
+ description : "OKE operator policy."
+ compartment_id : ""
+ statements : [
+ "allow dynamic-group oke-operator-dynamic-group to manage cluster-family in compartment "
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/oke-operator-host-iam/main.tf b/cis-oke/examples/flannel/oke-operator-host-iam/main.tf
new file mode 100644
index 0000000..a634cbc
--- /dev/null
+++ b/cis-oke/examples/flannel/oke-operator-host-iam/main.tf
@@ -0,0 +1,11 @@
+module "operator_dynamic_group" {
+ source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-iam//dynamic-groups?ref=v0.2.0"
+ tenancy_ocid = var.tenancy_ocid
+ dynamic_groups_configuration = var.dynamic_groups_configuration
+}
+
+module "operator_policy" {
+ source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-iam//policies?ref=v0.2.0"
+ tenancy_ocid = var.tenancy_ocid
+ policies_configuration = var.policies_configuration
+}
\ No newline at end of file
diff --git a/cis-oke/examples/flannel/oke-operator-host-iam/providers.tf b/cis-oke/examples/flannel/oke-operator-host-iam/providers.tf
new file mode 100644
index 0000000..6c2673e
--- /dev/null
+++ b/cis-oke/examples/flannel/oke-operator-host-iam/providers.tf
@@ -0,0 +1,22 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.home_region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+ ignore_defined_tags = ["Oracle-Tags.CreatedBy", "Oracle-Tags.CreatedOn"]
+}
+
+terraform {
+ required_version = "< 1.3.0"
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+ experiments = [module_variable_optional_attrs]
+}
diff --git a/cis-oke/examples/flannel/oke-operator-host-iam/variables.tf b/cis-oke/examples/flannel/oke-operator-host-iam/variables.tf
new file mode 100644
index 0000000..82d7251
--- /dev/null
+++ b/cis-oke/examples/flannel/oke-operator-host-iam/variables.tf
@@ -0,0 +1,13 @@
+variable "tenancy_ocid" {}
+variable "home_region" { description = "Your tenancy home region" }
+variable "user_ocid" { default = "" }
+variable "fingerprint" { default = "" }
+variable "private_key_path" { default = "" }
+variable "private_key_password" { default = "" }
+
+variable "dynamic_groups_configuration" {
+ type = any
+}
+variable "policies_configuration" {
+ type = any
+}
\ No newline at end of file
diff --git a/cis-oke/examples/native/basic-access-from-localhost/README.md b/cis-oke/examples/native/basic-access-from-localhost/README.md
new file mode 100644
index 0000000..b122299
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-localhost/README.md
@@ -0,0 +1,95 @@
+# OKE NPN (Native Pod Networking) with Localhost Access Example
+
+## Introduction
+
+This example shows how to deploy OKE clusters and node pools in OCI using the [cis-oke module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke). It deploys one NPN basic OKE Cluster, one node pool, one Bastion service endpoint and one Bastion session for cluster management with the characteristics described below.
+
+### Pre-Requisite
+
+The OKE cluster and the node pool depend on a pre existing Virtual Cloud Network (VCN). A VCN built specifically for this deployment is available at [native network example](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-networking/tree/main/examples/oke-examples/native).
+
+### Resources Deployed by this Example
+
+OKE Cluster (OKE1):
+- of *basic* type.
+- set with the latest Kubernetes version;
+- with NPN (Native Pod Networking) CNI;
+- with a private API endpoint.
+
+Node Pool (NODEPOOL1):
+- created in the same compartment as the cluster;
+- with the same Kubernetes version as the cluster;
+- with one worker node (it is set by *workers_configuration.node_pools.NODEPOOL1.size* attribute);
+- node has the "VM.Standard.E4.Flex" shape;
+- node has 16 GB memory and 1 OCPU by default;
+- node boot volume size is 60GB and is terminated when the node is destroyed.
+
+Commented Virtual Node Pool (VIRTUALPOOL1):
+- created in the same compartment as the cluster;
+- with one worker node;
+- node has the "VM.Standard.E4.Flex" shape;
+
+Bastion Service (BASTION-1):
+- of *standard* type.
+
+Bastion Session (SESSION-1):
+- of **PORT_FORWARDING** type, allowing port forwarding to the OKE API endpoint;
+- targeting the OKE1 cluster API endpoint on port 6443.
+
+### How to Create Virtual Node Pools
+
+For adding a virtual node pool to the cluster, set the attribute *is_enhanced* to *true* and uncomment the *virtual_node_pools* attribute. Virtual node pools only work on enhanced clusters.
+
+For having the cluster with **only** virtual node pools, comment/remove the *node_pools* attribute.
+
+See [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+## Using this example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-oke module README.md](../../../README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
+
+## Accessing the Cluster
+
+Managing Kubernetes applications in OCI includes the ability to invoke OKE API endpoint and SSH'ing into Worker nodes.
+Invoking the OKE API endpoint and accessing Worker nodes differs depending on whether they are in a private or public subnet. This example assumes the API endpoint and Worker nodes are in private subnets and are invoked/accessed via an OCI Bastion Service endpoint that is deployed in the Access subnet, which is also private.
+
+### Accessing OKE API Endpoint
+
+The code automatically creates a *kubeconfig* file in the Terraform configuration folder, required for accessing the OKE API endpoint.
+
+To connect to the OKE API endpoint, in a terminal, execute the command provided in the **sessions** output, that would look like:
+```
+ssh -i ~/.ssh/id_rsa -N -L 6443:10.0.x.x:6443 -p 22 ocid1.bastionsession.oc1...@host.bastion.eu-frankfurt-1.oci.oraclecloud.com
+```
+
+Following that, in another terminal, set the KUBECONFIG environment variable to the *kubeconfig* file that was created in the Terraform configuration folder.
+```
+export KUBECONFIG =
+```
+
+You are now all set to use *kubectl* tool to manage your OKE applications. As an example, you can try deploying a sample application, checking and deleting it:
+```
+> kubectl create -f https://k8s.io/examples/application/deployment.yaml
+> kubectl get deployments
+> kubectl delete -f https://k8s.io/examples/application/deployment.yaml
+```
+
+### Connecting to Worker Nodes with SSH
+
+1. Using the Console, enable the Cloud Agent Bastion plugin in the worker node.
+2. Using the Console, create a managed SSH session for the worker node in the provisioned OCI Bastion service.
+3. Connect to worker node using the SSH command provided for the managed SSH session. The command looks like:
+```
+ssh -o ProxyCommand="ssh -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXXX@host.bastion.us-phoenix-1.oci.oraclecloud.com" -p 22 opc@
+```
diff --git a/cis-oke/examples/native/basic-access-from-localhost/input.auto.tfvars.template b/cis-oke/examples/native/basic-access-from-localhost/input.auto.tfvars.template
new file mode 100644
index 0000000..d877fc0
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-localhost/input.auto.tfvars.template
@@ -0,0 +1,166 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+# tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+# user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+# fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+# private_key_path = "" # This is the full path on your local system to the API signing private key.
+# private_key_password = "" # This is the password that protects the private key, if any.
+# region = "" # The region name.
+
+
+#---------------------------------------
+# Input variable
+#---------------------------------------
+
+clusters_configuration = {
+ default_compartment_id = ""
+ clusters = {
+ OKE1 = {
+ name = "oke-npn-cluster"
+ cni_type = "native"
+ is_enhanced = false
+ networking = {
+ vcn_id = ""
+ api_endpoint_subnet_id = ""
+ services_subnet_id = [""]
+ api_endpoint_nsg_ids = [""]
+ }
+ }
+ }
+}
+
+workers_configuration = {
+ default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+ node_pools = {
+ NODEPOOL1 = {
+ cluster_id = "OKE1"
+ name = "node-pool"
+ size = 1
+ networking = {
+ workers_subnet_id = ""
+ pods_subnet_id = ""
+ workers_nsg_ids = [""]
+ pods_nsg_ids = [""]
+ }
+ node_config_details = {
+ node_shape = "VM.Standard.E4.Flex"
+ }
+ }
+ # virtual_node_pools = {
+ # VIRTUALPOOL1 = {
+ # cluster_id = "OKE1"
+ # name = "virtual-node-pool"
+ # pod_shape = "Pod.Standard.E4.Flex"
+ # size = 1
+ # networking = {
+ # workers_subnet_id = ""
+ # pods_subnet_id = ""
+ # workers_nsg_ids = [""]
+ # pods_nsg_ids = [""]
+ # }
+ # }
+ # }
+ }
+}
+
+bastions_configuration = {
+ bastions = {
+ BASTION-1 = {
+ bastion_type = "STANDARD"
+ compartment_id = ""
+ subnet_id = ""
+ cidr_block_allow_list = [""] # Try to be as much specific as possible, and avoid entering "0.0.0.0/0".
+ name = "OkeNpnBastionByTerraform"
+ }
+ }
+}
+
+sessions_configuration = {
+ sessions = {
+ SESSION-1 = {
+ bastion_id = "BASTION-1"
+ ssh_public_key = ""
+ session_type = "PORT_FORWARDING"
+ target_resource = "OKE1"
+ target_port = "6443"
+ session_name = "PortForwardingByTerraform"
+ }
+ }
+}
+
+###----------------------------------------------------------------------
+### Below a real assignment with OCIDs redacted.
+###----------------------------------------------------------------------
+
+#clusters_configuration = {
+# default_compartment_id = "ocid1.compartment.oc1..aaaaaaaaa...w2q"
+# clusters = {
+# OKE1 = {
+# name = "oke-npn-cluster"
+# cni_type = "native"
+# is_enhanced = false
+# networking = {
+# vcn_id = "ocid1.vcn.oc1.phx.amaaaaaa...h5q"
+# api_endpoint_nsg_ids = ["ocid1.networksecuritygroup.oc1.phx.aaaaaaaa...p5a"]
+# api_endpoint_subnet_id = "ocid1.subnet.oc1.phx.aaaaaaaa...yxa"
+# services_subnet_id = ["ocid1.subnet.oc1.phx.aaaaaaaa...rfq"]
+# }
+# }
+# }
+#}
+
+#workers_configuration = {
+# default_ssh_public_key_path = "~/.ssh/id_rsa.pub"
+# node_pools = {
+# NODEPOOL1 = {
+# cluster_id = "OKE1"
+# name = "node-pool"
+# size = 1
+# networking = {
+# workers_nsg_ids = ["ocid1.networksecuritygroup.oc1.phx.aaaaaaaa...fyq"]
+# workers_subnet_id = "ocid1.subnet.oc1.phx.aaaaaaaa...voa"
+# pods_subnet_id = "ocid1.subnet.oc1.phx.aaaaaaaa...c4q"
+# pods_nsg_ids = ["ocid1.networksecuritygroup.oc1.phx.aaaaaaaa...wdq"]
+# }
+# node_config_details = {
+# node_shape = "VM.Standard.E4.Flex"
+# }
+# }
+# }
+#}
+
+#bastions_configuration = {
+# bastions = {
+# BASTION-1 = {
+# bastion_type = "STANDARD"
+# compartment_id = "ocid1.compartment.oc1..aaaaaaaa...qfa"
+# subnet_id = "ocid1.subnet.oc1.phx.aaaaaaaa...uja"
+# cidr_block_allow_list = ["999.9.99.999/32"]
+# name = "OkeNpnBastionByTerraform"
+# }
+# }
+#}
+
+#sessions_configuration = {
+# sessions = {
+# PORT-FORWARDING-SESSION = {
+# bastion_id = "BASTION-1"
+# ssh_public_key = "~/.ssh/id_rsa.pub"
+# session_type = "PORT_FORWARDING"
+# target_resource = "OKE1"
+# target_port = "6443"
+# session_name = "PortForwardingByTerraform"
+# }
+# }
+#}
\ No newline at end of file
diff --git a/cis-oke/examples/native/basic-access-from-localhost/main.tf b/cis-oke/examples/native/basic-access-from-localhost/main.tf
new file mode 100644
index 0000000..a5d253f
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-localhost/main.tf
@@ -0,0 +1,27 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+module "oke" {
+ source = "../../../"
+ clusters_configuration = var.clusters_configuration
+ workers_configuration = var.workers_configuration
+}
+
+module "bastion" {
+ source = "github.com/oracle-quickstart/terraform-oci-cis-landing-zone-security.git//bastion?ref=v0.1.4"
+ bastions_configuration = var.bastions_configuration
+ sessions_configuration = var.sessions_configuration
+ endpoints_dependency = {for k, v in module.oke.clusters : k => {"ip_address" : split(":",v.endpoints[0].private_endpoint)[0]}}
+}
+
+data "oci_containerengine_cluster_kube_config" "kube_config" {
+ for_each = var.clusters_configuration != null ? var.clusters_configuration["clusters"] : {}
+ cluster_id = module.oke.clusters[each.key].id
+ token_version = "2.0.0"
+}
+
+resource "local_file" "kubeconfig" {
+ for_each = var.clusters_configuration != null ? var.clusters_configuration["clusters"] : {}
+ content = tostring(replace(data.oci_containerengine_cluster_kube_config.kube_config[each.key].content, split(":", module.oke.clusters[each.key].endpoints[0].private_endpoint)[0], "127.0.0.1"))
+ filename = "./kubeconfig"
+}
diff --git a/cis-oke/examples/native/basic-access-from-localhost/outputs.tf b/cis-oke/examples/native/basic-access-from-localhost/outputs.tf
new file mode 100644
index 0000000..af3e20a
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-localhost/outputs.tf
@@ -0,0 +1,16 @@
+
+# Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+
+output "clusters" {
+ value = module.oke.clusters
+}
+
+output "node_pools" {
+ value = module.oke.node_pools
+}
+
+output "sessions" {
+ value = module.bastion.sessions
+}
diff --git a/cis-oke/examples/native/basic-access-from-localhost/providers.tf b/cis-oke/examples/native/basic-access-from-localhost/providers.tf
new file mode 100644
index 0000000..4bd8b69
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-localhost/providers.tf
@@ -0,0 +1,20 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+provider "oci" {
+ region = var.region
+ tenancy_ocid = var.tenancy_ocid
+ user_ocid = var.user_ocid
+ fingerprint = var.fingerprint
+ private_key_path = var.private_key_path
+ private_key_password = var.private_key_password
+ ignore_defined_tags = ["Oracle-Tags.CreatedBy", "Oracle-Tags.CreatedOn"]
+}
+
+terraform {
+ required_providers {
+ oci = {
+ source = "oracle/oci"
+ }
+ }
+}
diff --git a/cis-oke/examples/native/basic-access-from-localhost/variables.tf b/cis-oke/examples/native/basic-access-from-localhost/variables.tf
new file mode 100644
index 0000000..05e047f
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-localhost/variables.tf
@@ -0,0 +1,22 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+variable "tenancy_ocid" {}
+variable "region" { description = "Your tenancy region" }
+variable "user_ocid" { default = "" }
+variable "fingerprint" { default = "" }
+variable "private_key_path" { default = "" }
+variable "private_key_password" { default = "" }
+
+variable "clusters_configuration" {
+ type = any
+}
+variable "workers_configuration" {
+ type = any
+}
+variable "bastions_configuration" {
+ type = any
+}
+variable "sessions_configuration" {
+ type = any
+}
diff --git a/cis-oke/examples/native/basic-access-from-operator-host/README.md b/cis-oke/examples/native/basic-access-from-operator-host/README.md
new file mode 100644
index 0000000..613882d
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-operator-host/README.md
@@ -0,0 +1,134 @@
+# OKE NPN (Native Pod Networking) with Operator Access Example
+
+## Introduction
+
+This example shows how to deploy OKE clusters and node pools in OCI using the [cis-oke module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke). It deploys one NPN basic OKE Cluster, one node pool, one Bastion service endpoint, one Bastion session, and one Compute instance with the characteristics described below.
+
+Once the cluster is provisioned, cluster access is automatically enabled from the provisioned Compute instance, which is accessible via the OCI Bastion service endpoint. We refer to this Compute instance as the Operator host.
+
+### Pre-Requisites
+
+#### Networking
+The OKE cluster and the node pool depend on a pre existing Virtual Cloud Network (VCN). A VCN built specifically for this deployment is available in [native network example](https://github.com/oracle-quickstart/terraform-oci-cis-landing-zone-networking/tree/main/examples/oke-examples/native).
+
+Additionally, the Operator host requires an instance principal credential properly authorized for managing the OKE cluster. That means a dynamic group and a policy are required.
+
+#### IAM Dynamic Group and Policy
+##### Dynamic Group Matching Rule
+```
+instance.compartment.id=''
+```
+
+##### Dynamic Group Policy
+```
+Allow dynamic-group to manage cluster-family in compartment
+```
+
+The deployment of these IAM resources are automated by the [OKE Operator Host IAM example](../../flannel/oke-operator-host-iam/).
+
+
+### Resources Deployed by this Example
+
+OKE cluster (OKE1):
+- of *basic* type;
+- set with the latest Kubernetes version;
+- with Flannel CNI;
+- with a private API endpoint.
+
+Node pool (NODEPOOL1):
+- created in the same compartment as the cluster;
+- with the same Kubernetes version as the cluster;
+- with one worker node (it is set by *workers_configuration.node_pools.NODEPOOL1.size* attribute);
+- node has the "VM.Standard.E4.Flex" shape;
+- node has 16 GB memory and 1 OCPU by default;
+- node boot volume size is 60GB and is terminated when the node is destroyed.
+
+Compute instance (INSTANCE-1), a.k.a. Operator host:
+- based on "VM.Standard.E4.Flex" shape, as defined by the *shape* attribute.
+- based on the "Oracle-Linux-Cloud-Developer-8.7-2023.04.28-1" platform image, as defined by *image.id* attribute.
+ - Either use the [platform-images module](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/platform-images) to find Platform images information based on a search filter or search for the region-specific image OCID in [All Image Families](https://docs.oracle.com/en-us/iaas/images/).
+- it does **not** have the boot volume preserved on termination, as defined by *boot_volume.preserve_on_instance_deletion* attribute.
+- the boot volume is set to be backed up per Oracle-managed *bronze* backup policy (enforced by the module by default).
+- the instance enables the Cloud Agent Bastion plugin, enabling it to accept SSH connections from OCI Bastion service.
+
+Bastion Service endpoint (BASTION-1):
+- created in the same subnet as the Operator host.
+
+Bastion session (SESSION-1):
+- of **MANAGED_SSH** type, allowing SSH connectivity to the Operator host.
+
+See [input.auto.tfvars.template](./input.auto.tfvars.template) for the variables configuration.
+
+## Using this Example
+1. Rename *input.auto.tfvars.template* to *\.auto.tfvars*, where *\* is any name of your choice.
+
+2. Within *\.auto.tfvars*, provide tenancy connectivity information and adjust the input variables, by making the appropriate substitutions:
+ - Replace \ placeholders with appropriate values.
+
+Refer to [cis-oke module README.md](https://github.com/oracle-quickstart/terraform-oci-secure-workloads/tree/main/cis-oke/README.md) for overall attributes usage.
+
+3. In this folder, run the typical Terraform workflow:
+```
+terraform init
+terraform plan -out plan.out
+terraform apply plan.out
+```
+
+## Accessing the Cluster
+
+Managing Kubernetes applications in OCI includes the ability to invoke OKE API endpoint and SSH'ing into worker nodes.
+Invoking the OKE API endpoint and accessing worker nodes differs depending on whether they are in a private or public subnet. This example assumes the API endpoint and worker nodes are in private subnets and are invoked/accessed from the Operator host, which is reachable via the OCI Bastion service.
+
+The code automatically connects to the Operator host using the Bastion service session to configure the *kubeconfig* file, install *kubectl* tool and set the instance with instance principal authentication.
+
+For connecting to the Operator host, execute the command provided in the **sessions** output, that would look like:
+```
+ssh -i -o ProxyCommand='ssh -i -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXX@host.bastion.oci.oraclecloud.com' -p 22 opc@
+```
+
+### Accessing OKE API Endpoint
+
+One connected to the Operator host, use *kubectl* tool to manage your OKE applications. As an example, you can try deploying a sample application, checking and deleting it:
+```
+> kubectl create -f https://k8s.io/examples/application/deployment.yaml
+> kubectl get deployments
+> kubectl delete -f https://k8s.io/examples/application/deployment.yaml
+```
+
+If for some reason *kubectl* does not get installed, once connected to the host, execute the [install_kubectl.sh](./install_kubectl.sh) script manually.
+
+After installing *kubectl*, if you can't get access to the cluster, confirm there is a *config* file under *$HOME/.kube*. Otherwise, manually create *kubeconfig* file, by executing:
+```
+oci ce cluster create-kubeconfig --cluster-id --file $HOME/.kube/config --region --token-version 2.0.0 --kube-endpoint PRIVATE_ENDPOINT
+```
+**Note**: the command above can be obtained in OCI Console, navigating to the "Quick Start" link within the OKE cluster.
+
+### Connecting to Worker Nodes via SSH
+
+This is done from the Operator host:
+
+1. Make the SSH private key that matches the SSH public key in the worker node available in the Operator host. If the private key is available in your local machine, it can be copied to the Operator host like:
+```
+scp -J ocid1.bastionsession.XXXXXXXX@host.bastion.oci.oraclecloud.com opc@:
+```
+2. Connect to the Operator host using the SSH command in the **sessions** output:
+```
+ssh -i -o ProxyCommand='ssh -i -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXX@host.bastion.oci.oraclecloud.com' -p 22 opc@
+```
+3. Restrict permissions on the private SSH key:
+```
+chmod 600
+```
+4. Connect to the worker node via SSH:
+```
+ssh -i opc@
+```
+
+Optionally, you can manually create a managed SSH session for the worker node in the provisioned OCI Bastion service, bypassing the Operator host altogether.
+
+1. Using the Console, enable the Cloud Agent Bastion plugin in the worker node.
+2. Using the Console, create a managed SSH session for the worker node in the provisioned OCI Bastion service.
+3. Connect to worker node using the SSH command provided for the managed SSH session. The command looks like:
+```
+ssh -o ProxyCommand="ssh -W %h:%p -p 22 ocid1.bastionsession.XXXXXXXXX@host.bastion.us-phoenix-1.oci.oraclecloud.com" -p 22 opc@
+```
\ No newline at end of file
diff --git a/cis-oke/examples/native/basic-access-from-operator-host/input.auto.tfvars.template b/cis-oke/examples/native/basic-access-from-operator-host/input.auto.tfvars.template
new file mode 100644
index 0000000..47b297e
--- /dev/null
+++ b/cis-oke/examples/native/basic-access-from-operator-host/input.auto.tfvars.template
@@ -0,0 +1,146 @@
+# Copyright (c) 2023 Oracle and/or its affiliates.
+# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
+
+#--------------------------------------------------------------------------------------------------------------------------------------
+# 1. Rename this file to .auto.tfvars, where is a name of your choice.
+# 2. Provide values for "Tenancy Connectivity Variables".
+# 3. Replace placeholders with appropriate values.
+#--------------------------------------------------------------------------------------------------------------------------------------
+
+#---------------------------------------
+# Tenancy Connectivity Variables
+#---------------------------------------
+
+# tenancy_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "Tenancy: ").
+# user_ocid = "" # Get this from OCI Console (after logging in, go to top-right-most menu item and click option "My profile").
+# fingerprint = "" # The fingerprint can be gathered from your user account. In the "My profile page, click "API keys" on the menu in left hand side.
+# private_key_path = "" # This is the full path on your local system to the API signing private key.
+# private_key_password = "" # This is the password that protects the private key, if any.
+# region = "" # The region name.
+
+#---------------------------------------
+# Input variable
+#---------------------------------------
+
+clusters_configuration = {
+ default_compartment_id = "