├── .gitignore ├── README.md ├── docs └── images │ └── ocne_infrastructure.png ├── locals.tf ├── main.tf ├── modules ├── oci-ocne-autoscaling │ ├── .gitignore │ ├── README.md │ ├── datasources.tf │ ├── locals.tf │ ├── main.tf │ ├── output.tf │ ├── variables.tf │ └── versions.tf ├── oci-ocne-compute │ ├── .gitignore │ ├── README.md │ ├── main.tf │ ├── output.tf │ ├── variables.tf │ └── versions.tf ├── oci-ocne-images │ ├── README.md │ ├── datasources.tf │ ├── output.tf │ ├── variables.tf │ └── versions.tf ├── oci-ocne-kms │ ├── .gitignore │ ├── README.md │ ├── datasources.tf │ ├── locals.tf │ ├── main.tf │ ├── output.tf │ ├── variables.tf │ └── versions.tf ├── oci-ocne-loadbalancer │ ├── .gitignore │ ├── README.md │ ├── main.tf │ ├── output.tf │ ├── variables.tf │ └── versions.tf ├── oci-ocne-network │ ├── README.md │ ├── main.tf │ ├── output.tf │ ├── terraform.tfvars.example │ ├── variables.tf │ └── versions.tf ├── ocne-provision │ ├── .gitignore │ ├── config-file.yaml.example │ ├── datasources.tf │ ├── files │ │ ├── config-edit.sh │ │ ├── config-read.sh │ │ └── provision.template.sh │ ├── main.tf │ ├── variables.tf │ └── versions.tf ├── terraform-oci-bastion │ ├── CHANGELOG.adoc │ ├── CONTRIBUTING.adoc │ ├── CONTRIBUTORS.adoc │ ├── LICENSE │ ├── README.adoc │ ├── README.md │ ├── cloudinit │ │ └── autonomous.template.yaml │ ├── compute.tf │ ├── datasources.tf │ ├── docs │ │ ├── prerequisites.adoc │ │ ├── quickstart.adoc │ │ └── terraformoptions.adoc │ ├── examples │ │ ├── README.md │ │ ├── main.tf │ │ ├── terraform.tfvars.example │ │ └── variables.tf │ ├── locals.tf │ ├── ons.tf │ ├── outputs.tf │ ├── scripts │ │ └── notification.template.sh │ ├── security.tf │ ├── subnets.tf │ ├── terraform.tfvars.example │ ├── variables.tf │ └── versions.tf ├── terraform-oci-ocne-infrastructure │ ├── .gitignore │ ├── README.md │ ├── files │ │ ├── agent_init.sh │ │ └── apiserver_init.sh │ ├── locals.tf │ ├── main.tf │ ├── output.tf │ ├── variables.tf │ └── versions.tf └── terraform-oci-vault │ ├── .gitignore │ ├── README.md │ ├── datasources.tf │ ├── main.tf │ ├── output.tf │ ├── templates │ ├── cloudinit.template │ ├── fetch_token │ ├── ocne-cert-engine-policy.hcl │ ├── vault.template │ ├── vault_env │ └── vault_setup │ ├── variables.tf │ └── versions.tf ├── output.tf ├── provider.tf ├── state_backend.tf.example ├── terraform.tfvars.example ├── variables.tf └── versions.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | .terraform 10 | 11 | # Crash log files 12 | crash.log 13 | *.txt 14 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 15 | # .tfvars files are managed as part of configuration and so should be included in 16 | # version control. 17 | # 18 | # example.tfvars 19 | 20 | # Ignore override files as they are usually used to override resources locally and so 21 | # are not checked in 22 | override.tf 23 | override.tf.json 24 | *_override.tf 25 | *_override.tf.json 26 | 27 | # Include override files you do wish to add to version control using negated pattern 28 | # 29 | # !example_override.tf 30 | 31 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 32 | # example: *tfplan* 33 | 34 | ### JetBrains template 35 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 36 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 37 | 38 | # User-specific stuff 39 | .idea/ 40 | .idea/**/workspace.xml 41 | .idea/**/tasks.xml 42 | .idea/**/usage.statistics.xml 43 | .idea/**/dictionaries 44 | .idea/**/shelf 45 | 46 | # Generated files 47 | .idea/**/contentModel.xml 48 | 49 | # Sensitive or high-churn files 50 | .idea/**/dataSources/ 51 | .idea/**/dataSources.ids 52 | .idea/**/dataSources.local.xml 53 | .idea/**/sqlDataSources.xml 54 | .idea/**/dynamic.xml 55 | .idea/**/uiDesigner.xml 56 | .idea/**/dbnavigator.xml 57 | 58 | # Gradle 59 | .idea/**/gradle.xml 60 | .idea/**/libraries 61 | 62 | # Gradle and Maven with auto-import 63 | # When using Gradle or Maven with auto-import, you should exclude module files, 64 | # since they will be recreated, and may cause churn. Uncomment if using 65 | # auto-import. 66 | # .idea/modules.xml 67 | # .idea/*.iml 68 | # .idea/modules 69 | # *.iml 70 | # *.ipr 71 | 72 | # CMake 73 | cmake-build-*/ 74 | 75 | # Mongo Explorer plugin 76 | .idea/**/mongoSettings.xml 77 | 78 | # File-based project format 79 | *.iws 80 | 81 | # IntelliJ 82 | out/ 83 | 84 | # mpeltonen/sbt-idea plugin 85 | .idea_modules/ 86 | 87 | # JIRA plugin 88 | atlassian-ide-plugin.xml 89 | 90 | # Cursive Clojure plugin 91 | .idea/replstate.xml 92 | 93 | # Crashlytics plugin (for Android Studio and IntelliJ) 94 | com_crashlytics_export_strings.xml 95 | crashlytics.properties 96 | crashlytics-build.properties 97 | fabric.properties 98 | 99 | # Editor-based Rest Client 100 | .idea/httpRequests 101 | 102 | # Android studio 3.1+ serialized cache file 103 | .idea/caches/build_file_checksums.ser 104 | 105 | 106 | # Terraform config 107 | modules/certs 108 | .terraform.lock.hcl 109 | kubeconfig 110 | state-backend.tf 111 | terraform_vars.sh 112 | terraform.tfvars 113 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Terraform for Oracle Cloud Native Environment 2 | 3 | ## Introduction 4 | 5 | This repository is the top level for a modularized method for deploying OCNE and its subcomponents into OCI using terraform. Each submodule focuses on a specific portion of an OCNE deploymnent, allowing users to select specific configurations to deploy. 6 | 7 | This module will create the following resources: 8 | 9 | ![OCNE Infrastructure diagram:](/docs/images/ocne_infrastructure.png) 10 | * **OCNE API Server**: The OCNE API Server to orchestrate OCNE agents running on Control Plane and Worker nodes to perform installation of Kubernetes and other OCNE modules. 11 | * **Control Plane Nodes**: The compute instances for the Control Plane Nodes of Kubernetes cluster. 12 | * **Worker Nodes**: The compute instances for the Worker Nodes of Kubernetes cluster. 13 | * **Kubernetes API Load Balancer**: The Load Balancer to distribute Kubernetes API requrests to the Control Plane Nodes. 14 | 15 | ### High-Level Deployment Options 16 | 17 | This module supports several common deployment scenarios out of the box. They are listed here to avoid having to duplicated them in each of the relevant module descriptions below 18 | 19 | * OCNE API Server on a dedicated compute instance 20 | * Passing in a default network to build the deployment in 21 | * Allowing these modules to create and configure a new network 22 | * Use openssl to generate and distribute certificates to each node 23 | 24 | ## Getting Started 25 | 26 | ### Install Terraform 27 | Start by installing Terraform and configuring your path. 28 | 29 | #### Download Terraform 30 | 31 | 1. Open your browser and navigate to the [Terraform download page](https://www.terraform.io/downloads.html). You need version 1.0.0+. 32 | 2. Download the appropriate version for your operating system 33 | 3. Extract the contents of compressed file and copy the terraform binary to a location that is in your path (see next section below) 34 | 35 | #### Configure path on Linux/macOS 36 | Open a terminal and type the following: 37 | 38 | ``` 39 | $ sudo mv /path/to/terraform /usr/local/bin 40 | ``` 41 | 42 | #### Configure path on Windows 43 | Follow the steps below to configure your path on Windows: 44 | 45 | 1. Click on 'Start', type 'Control Panel' and open it 46 | 2. Select System > Advanced System Settings > Environment Variables 47 | 3. Select System variables > PATH and click 'Edit' 48 | 4. Click New and paste the location of the directory where you have extracted the terraform.exe 49 | 5. Close all open windows by clicking OK 50 | 6. Open a new terminal and verify terraform has been properly installed 51 | 52 | #### Testing Terraform installation 53 | Open a terminal and test: 54 | 55 | ``` 56 | terraform -v 57 | ``` 58 | 59 | #### Install jq and yq 60 | The OCNE provision module uses jq and yq to process yaml files 61 | 1. Install yq (>= 4.16): https://github.com/mikefarah/yq#install 62 | 2. Install jq (>= 1.5): https://stedolan.github.io/jq/download/ 63 | 64 | ### Generate API keys 65 | 66 | Follow the documentation for generating keys on [OCI Documentation](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#two). 67 | 68 | ### Upload your API keys 69 | 70 | Follow the documentation for uploading your keys on [OCI Documentation](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#two). 71 | 72 | Note the fingerprint. 73 | 74 | ### Create an OCI compartment 75 | 76 | Follow the documentation for [creating a compartment](https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingcompartments.htm#two). 77 | 78 | ### Obtain the necessary OCIDs 79 | 80 | The following OCIDs are required: 81 | 82 | 1. Compartment OCID 83 | 2. Tenancy OCID 84 | 3. User OCID 85 | 86 | Follow the documentation for obtaining the tenancy and user ids on [OCI Documentation](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#five). 87 | 88 | To obtain the compartment OCID: 89 | 90 | 1. Navigate to Identity > Compartments 91 | 2. Click on your Compartment 92 | 3. Locate OCID on the page and click on 'Copy' 93 | 94 | ### Deploy OCNE using terraform 95 | 96 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module (i.e. here). This module deploys a complete OCNE stack including a Kubernetes cluster. 97 | 98 | The terraform.tfvars.example file can be renamed as terraform.tfvars to set the [input variables](https://www.terraform.io/docs/language/values/variables.html#assigning-values-to-root-module-variables) for the `terraform-oci-olcne` module. Please refer to the variable 99 | descriptions in variables.tf for information about how each is used. 100 | 101 | #### Overview of terraform.tfvars.example file variables 102 | 103 | | Name |Description | 104 | |:---------- |:-----------| 105 | |tenancy_id|The OCID of your tenancy. To get the value, see [Where to Get the Tenancy's OCID and User's OCID](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#five).| 106 | |compartment_id|The OCID of the compartment.| 107 | |user_id|The OCID of the user that will be used by terraform to create OCI resources. To get the value, see Where to Get the Tenancy's OCID and User's OCID.| 108 | |fingerprint|Fingerprint for the key pair being used. To get the value, see [How to Get the Key's Fingerprint](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#four)| 109 | |api_private_key_path|The path to the private key used by the OCI user to authenticate with OCI API's. For details on how to create and configure keys see [How to Generate an API Signing Key ](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#two) and [How to Upload the Public Key](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/apisigningkey.htm#three).| 110 | |region|The OCI region where resources will be created. To get the value, See [Regions and Availability Domains](https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm#top).| 111 | |availability_domain_id|The ID of the availability domain inside the `region` to create the deployment| 112 | |prefix|A unique prefix to attach to the name of all OCNE resources that are created as a part of the deployment.| 113 | |ssh_private_key_path|The SSH private key path that goes with the SSH public key that is used when accessing compute resources that are created as part of this deployment. To generate the keys see - [Generating an SSH Key Pair for Oracle Compute Cloud Service Instances](https://www.oracle.com/webfolder/technetwork/tutorials/obe/cloud/compute-iaas/generating_ssh_key/generate_ssh_key.html).| 114 | |ssh_public_key_path|The SSH public key path to use when configuring access to any compute resources created as part of this deployment. To generate the keys see - [Generating an SSH Key Pair for Oracle Compute Cloud Service Instances](https://www.oracle.com/webfolder/technetwork/tutorials/obe/cloud/compute-iaas/generating_ssh_key/generate_ssh_key.html).| 115 | |control_plane_node_count|The number of Kubernetes control plane nodes to deploy. To view the recommended worker node count, please see [Kubernetes High Availability Requirements](https://docs.oracle.com/en/operating-systems/olcne/start/hosts.html#kube-nodes).| 116 | |worker_node_count|The number of Kubernetes worker nodes to deploy. To view the recommended worker node count, please see [Kubernetes High Availability Requirements](https://docs.oracle.com/en/operating-systems/olcne/start/hosts.html#kube-nodes).| 117 | |os_version|The version of Oracle Linux to use as the base image for all compute resources that are part of this deployemnt.| 118 | |environment_name|The name of the OCNE Environment that is created by this module to deploy module instances into. For more details, please see [Creating an Environment](https://docs.oracle.com/en/operating-systems/olcne/start/install.html#env-create).| 119 | |kubernetes_name|The name of the instance of the OCNE Kubernetes module that is installed as part of this deployment. For more details, please see [Creating a Kubernetes Module](https://docs.oracle.com/en/operating-systems/olcne/start/install.html#mod-kube).| 120 | |ocne_version|The version and release of OCNE to deploy. For more details on the versions, please see the [OCNE Release Notes](https://docs.oracle.com/en/operating-systems/olcne/1.7/relnotes/components.html#components). To install the latest patch version of , please set the value to `` or set the value to `` to install a specific patch version.| 121 | |config_file_path|The path to the OCNE configuration file. For more details on the configuration file, please see the [OCNE configuration file](https://docs.oracle.com/en/operating-systems/olcne/1.7/olcnectl/config.html)| 122 | 123 | #### Using Object Storage for State Files 124 | 125 | Using Object Storage statefile requires that you create an AWS S3 Compatible API Key on OCI. This can be done from both the OCI UI and CLI. For more details visit [Using Object Storage for State Files](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/terraformUsingObjectStore.htm#s3). 126 | 127 | To get started, rename `state_backend.tf.example` to `state_backend.tf` and fill out the appropriate variables. Variable definitions for the S3 Backend can be found in the [Hashicorp Terraform S3 Backend Documentation](https://www.terraform.io/docs/language/settings/backends/s3.html#credentials-and-shared-configuration). 128 | 129 | #### Deploying Environment 130 | 131 | Once all required variabes are set, source them and then initialise, validate and apply terraform. These commands must be run from within this module. 132 | 133 | 134 | - `terraform init` 135 | 136 | > The `terraform init` command is used to initialize a working directory containing Terraform configuration files. This is the first command that should be run after writing a new Terraform configuration or cloning an existing one from version control. It is safe to run this command multiple times. 137 | 138 | - `terraform validate` 139 | 140 | > The `terraform validate` command validates the configuration files in a directory, referring only to the configuration. 141 | 142 | - `terraform apply` 143 | 144 | > The `terraform apply` command is used to apply the changes required to reach the desired state of the configuration. 145 | 146 | ## License 147 | 148 | Copyright (c) 2019-2023 Oracle Corporation and/or affiliates. All rights reserved. 149 | Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 150 | -------------------------------------------------------------------------------- /docs/images/ocne_infrastructure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oracle-terraform-modules/terraform-oci-ocne/de1b79016ca7d143869cc968400cc08f954fc0cb/docs/images/ocne_infrastructure.png -------------------------------------------------------------------------------- /locals.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | locals { 5 | provision_modes_map = { 6 | provision_mode_ocne = "OCNE" 7 | provision_mode_infrastucture = "Infrastructure" 8 | } 9 | 10 | provision_modes_values_list = values(local.provision_modes_map) 11 | } 12 | 13 | locals { 14 | secret_name = "${var.prefix}-${var.secret_name}" 15 | ocne_secret_name = "${var.prefix}-${var.ocne_secret_name}" 16 | } -------------------------------------------------------------------------------- /main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | resource "null_resource" "variable_validation" { 5 | lifecycle { 6 | postcondition { 7 | condition = (contains(local.provision_modes_values_list, var.provision_mode)) 8 | error_message = "Invalid provision mode: ${var.provision_mode}. Valid provision modes are: ${join(", ", local.provision_modes_values_list)}" 9 | } 10 | postcondition { 11 | condition = (!var.deploy_networking || var.enable_bastion) 12 | error_message = "enable_bastion must be true if deploy_networking is true" 13 | } 14 | postcondition { 15 | condition = (!var.enable_bastion || (var.enable_bastion && var.bastion_private_key_path != "")) 16 | error_message = "bastion_private_key_path must be set if enable_bastion is true" 17 | } 18 | } 19 | } 20 | 21 | data "external" "ocne_config" { 22 | program = ["sh", "${path.module}/modules/ocne-provision/files/config-read.sh"] 23 | query = { 24 | path = var.config_file_path 25 | ov = var.ocne_version 26 | en = var.environment_name 27 | kn = var.kubernetes_name 28 | } 29 | } 30 | 31 | resource "null_resource" "ocne_config_validation" { 32 | depends_on = [data.external.ocne_config] 33 | lifecycle { 34 | postcondition { 35 | condition = (length(data.external.ocne_config.result.error) == 0) 36 | error_message = data.external.ocne_config.result.error 37 | } 38 | } 39 | } 40 | 41 | module "oci-ocne-network" { 42 | source = "./modules/oci-ocne-network" 43 | count = (var.deploy_networking && var.enable_bastion) || var.enable_bastion ? 1 : 0 44 | 45 | compartment_id = var.compartment_id 46 | ssh_public_key_path = var.ssh_public_key_path 47 | prefix = var.prefix 48 | deploy_networking = var.deploy_networking 49 | enable_bastion = var.enable_bastion 50 | vcn_id = var.vcn_id 51 | ig_route_id = var.ig_route_id 52 | nat_route_id = var.nat_route_id 53 | freeform_tags = var.freeform_tags 54 | } 55 | 56 | module "bastion" { 57 | source = "./modules/terraform-oci-bastion" 58 | count = var.enable_bastion ? 1 : 0 59 | 60 | bastion_shape = var.bastion_shape 61 | tenancy_id = var.tenancy_id 62 | compartment_id = var.compartment_id 63 | ig_route_id = var.deploy_networking ? module.oci-ocne-network[0].ig_route_id : var.ig_route_id 64 | vcn_id = var.deploy_networking ? module.oci-ocne-network[0].vcn_id : var.vcn_id 65 | prefix = var.prefix 66 | ssh_public_key_path = var.ssh_public_key_path 67 | enable_notification = var.enable_notification 68 | freeform_tags = var.freeform_tags 69 | } 70 | 71 | module "infrastructure" { 72 | depends_on = [null_resource.variable_validation] 73 | source = "./modules/terraform-oci-ocne-infrastructure" 74 | 75 | availability_domain_id = var.availability_domain_id 76 | compartment_id = var.compartment_id 77 | prefix = var.prefix 78 | subnet_id = var.deploy_networking ? module.oci-ocne-network[0].private_subnet_id.*.id[0] : var.subnet_id 79 | instance_shape = var.instance_shape 80 | image_ocid = var.image_ocid 81 | os_version = var.os_version 82 | kernel_version = var.kernel_version 83 | load_balancer_shape = var.load_balancer_shape 84 | ssh_public_key_path = var.ssh_public_key_path 85 | ssh_private_key_path = var.ssh_private_key_path 86 | control_plane_node_count = var.control_plane_node_count 87 | worker_node_count = var.worker_node_count 88 | standalone_api_server = var.standalone_api_server 89 | yum_repo_url = var.yum_repo_url 90 | ocne_version = data.external.ocne_config.result.version 91 | enable_bastion = var.enable_bastion 92 | bastion_public_ip = var.enable_bastion ? module.bastion[0].bastion_public_ip : var.bastion_public_ip 93 | bastion_user = var.bastion_user 94 | bastion_private_key_path = var.enable_bastion || var.bastion_public_ip != "" ? var.bastion_private_key_path : "" 95 | compute_user = var.compute_user 96 | freeform_tags = var.freeform_tags 97 | virtual_ip = var.virtual_ip 98 | } 99 | 100 | module "vault" { 101 | source = "./modules/terraform-oci-vault" 102 | count = var.use_vault ? 1 : 0 103 | 104 | user_id = var.user_id 105 | region = var.region 106 | tenancy_id = var.tenancy_id 107 | fingerprint = var.fingerprint 108 | api_private_key_path = var.api_private_key_path 109 | private_key_password = var.private_key_password 110 | availability_domain_id = var.availability_domain_id 111 | compartment_id = var.compartment_id 112 | prefix = "${var.prefix}-vault" 113 | subnet_id = var.deploy_networking ? module.oci-ocne-network[0].private_subnet_id.*.id[0] : var.subnet_id 114 | instance_shape = var.instance_shape 115 | ssh_public_key_path = var.ssh_public_key_path 116 | ssh_private_key_path = var.ssh_private_key_path 117 | load_balancer_port = "8200" 118 | proxy = var.proxy 119 | vault_ocid = var.vault_ocid 120 | key_ocid = var.key_ocid 121 | vault_namespace = var.vault_namespace 122 | load_balancer_ocid = module.infrastructure.load_balancer_ocid 123 | create_load_balancer = false 124 | load_balancer_ip = module.infrastructure.load_balancer_ip 125 | pool_size = var.vault_pool_size 126 | secret_name = local.secret_name 127 | ocne_secret_name = local.ocne_secret_name 128 | load_balancer_shape = var.load_balancer_shape 129 | enable_bastion = var.enable_bastion 130 | bastion_public_ip = var.enable_bastion ? module.bastion[0].bastion_public_ip : var.bastion_public_ip 131 | bastion_user = var.bastion_user 132 | bastion_private_key_path = var.enable_bastion || var.bastion_public_ip != "" ? var.bastion_private_key_path : "" 133 | compute_user = var.compute_user 134 | freeform_tags = var.freeform_tags 135 | } 136 | 137 | module "ocne-provision" { 138 | depends_on = [module.infrastructure] 139 | source = "./modules/ocne-provision" 140 | count = var.provision_mode == lookup(local.provision_modes_map, "provision_mode_ocne", "") ? 1 : 0 141 | 142 | ssh_public_key_path = var.ssh_public_key_path 143 | ssh_private_key_path = var.ssh_private_key_path 144 | os_version = var.os_version 145 | proxy = var.proxy 146 | no_proxy = var.no_proxy 147 | use_vault = var.use_vault 148 | control_plane_node_count = var.control_plane_node_count 149 | worker_node_count = var.worker_node_count 150 | control_plane_nodes = module.infrastructure.control_plane_nodes 151 | worker_nodes = module.infrastructure.worker_nodes 152 | apiserver_ip = module.infrastructure.apiserver_ip 153 | vault_uri = var.use_vault ? module.vault[0].uri : "" 154 | ocne_version = data.external.ocne_config.result.version 155 | environment_name = data.external.ocne_config.result.environment_name 156 | kubernetes_name = data.external.ocne_config.result.kubernetes_name 157 | kube_apiserver_port = var.kube_apiserver_port 158 | kube_apiserver_ip = var.virtual_ip ? module.infrastructure.kube_apiserver_virtual_ip : module.infrastructure.load_balancer_ip 159 | virtual_ip = var.virtual_ip 160 | container_registry = var.container_registry 161 | certificate_signing_token = var.use_vault ? module.vault[0].vault_ocne_client_token : "" 162 | enable_bastion = var.enable_bastion 163 | bastion_public_ip = var.enable_bastion ? module.bastion[0].bastion_public_ip : var.bastion_public_ip 164 | bastion_user = var.bastion_user 165 | bastion_private_key_path = var.enable_bastion || var.bastion_public_ip != "" ? var.bastion_private_key_path : "" 166 | node_ocids = module.infrastructure.node_ocids 167 | compute_user = var.compute_user 168 | debug = var.debug 169 | restrict_service_externalip_cidrs = var.restrict_service_externalip_cidrs 170 | config_file_path = var.config_file_path 171 | oci_api_key_path = data.external.ocne_config.result.oci_api_key_path 172 | kubevirt_config = data.external.ocne_config.result.kubevirt_config 173 | } 174 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # 28 | # !example_override.tf 29 | 30 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 31 | # example: *tfplan* 32 | 33 | ### JetBrains template 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | 104 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/README.md: -------------------------------------------------------------------------------- 1 | ## oci-ocne-autoscaling 2 | 3 | Deploys all resources for autoscaling OCI deployments. This includes instance pools, load balancers and their associated objects, as well as any configuration required. Note that it is not possible to synchronize on any per-compute-instance initialization from within this module. It is incumbent upon the caller to ensure that deployed resources are fully operational. 4 | 5 | ## Getting Started 6 | 7 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 8 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/datasources.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | data "oci_core_instance_pool_instances" "pool_instances" { 5 | compartment_id = var.compartment_id 6 | instance_pool_id = oci_core_instance_pool.instance_pool.id 7 | } 8 | 9 | data "oci_core_instance" "instances" { 10 | count = var.pool_size 11 | instance_id = data.oci_core_instance_pool_instances.pool_instances.instances[count.index].id 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/locals.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | locals { 5 | lb_ocid = var.create_load_balancer ? oci_load_balancer_load_balancer.lb[0].id : var.load_balancer_ocid 6 | } 7 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | resource "oci_load_balancer_load_balancer" "lb" { 5 | count = var.create_load_balancer ? 1 : 0 6 | compartment_id = var.compartment_id 7 | display_name = "${var.prefix}-load-balancer" 8 | shape = lookup(var.load_balancer_shape, "shape") 9 | subnet_ids = [var.subnet_id] 10 | is_private = "true" 11 | 12 | # Optional 13 | shape_details { 14 | minimum_bandwidth_in_mbps = lookup(var.load_balancer_shape, "flex_min") 15 | maximum_bandwidth_in_mbps = lookup(var.load_balancer_shape, "flex_max") 16 | } 17 | freeform_tags = var.freeform_tags 18 | } 19 | 20 | resource "oci_load_balancer_backend_set" "lb_backend" { 21 | health_checker { 22 | protocol = var.load_balancer_protocol 23 | port = var.load_balancer_port 24 | url_path = "/sys/health" 25 | } 26 | 27 | load_balancer_id = local.lb_ocid 28 | name = "${var.prefix}-lb-backend" 29 | policy = var.load_balancer_policy 30 | } 31 | 32 | resource "oci_core_instance_configuration" "instance_config" { 33 | compartment_id = var.compartment_id 34 | display_name = "${var.prefix}-instance-configuration" 35 | freeform_tags = var.freeform_tags 36 | 37 | instance_details { 38 | instance_type = "compute" 39 | 40 | launch_details { 41 | availability_domain = var.availability_domain_id 42 | compartment_id = var.compartment_id 43 | display_name = "${var.prefix}-compute" 44 | shape = lookup(var.instance_shape, "shape", "VM.Standard2.2") 45 | 46 | dynamic "shape_config" { 47 | for_each = length(regexall("Flex", lookup(var.instance_shape, "shape", "VM.Standard.E3.Flex"))) > 0 ? [1] : [] 48 | content { 49 | ocpus = max(1, lookup(var.instance_shape, "ocpus", 1)) 50 | memory_in_gbs = (lookup(var.instance_shape, "memory", 4) / lookup(var.instance_shape, "ocpus", 1)) > 64 ? (lookup(var.instance_shape, "ocpus", 1) * 16) : lookup(var.instance_shape, "memory", 4) 51 | } 52 | } 53 | 54 | source_details { 55 | source_type = "image" 56 | image_id = var.image_ocid 57 | boot_volume_size_in_gbs = lookup(var.instance_shape, "boot_volume_size", null) 58 | } 59 | 60 | metadata = { 61 | ssh_authorized_keys = file(var.ssh_public_key_path) 62 | user_data = var.instance_user_data 63 | } 64 | 65 | create_vnic_details { 66 | assign_public_ip = "false" 67 | subnet_id = var.subnet_id 68 | } 69 | } 70 | } 71 | } 72 | 73 | resource "oci_core_instance_pool" "instance_pool" { 74 | depends_on = [oci_load_balancer_backend_set.lb_backend] 75 | instance_configuration_id = oci_core_instance_configuration.instance_config.id 76 | compartment_id = var.compartment_id 77 | display_name = "${var.prefix}-instance-pool" 78 | size = var.pool_size 79 | freeform_tags = var.freeform_tags 80 | 81 | placement_configurations { 82 | availability_domain = var.availability_domain_id 83 | primary_subnet_id = var.subnet_id 84 | } 85 | 86 | load_balancers { 87 | backend_set_name = "${var.prefix}-lb-backend" 88 | load_balancer_id = local.lb_ocid 89 | port = var.load_balancer_port 90 | vnic_selection = "PrimaryVnic" 91 | } 92 | } 93 | 94 | resource "oci_load_balancer_listener" "listener" { 95 | depends_on = [oci_core_instance_pool.instance_pool, oci_load_balancer_backend_set.lb_backend] 96 | default_backend_set_name = oci_core_instance_pool.instance_pool.load_balancers[0].backend_set_name 97 | load_balancer_id = local.lb_ocid 98 | name = "${var.prefix}-listener" 99 | port = var.load_balancer_port 100 | protocol = var.load_balancer_protocol 101 | } 102 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "instances" { 5 | description = "Private IP addresses of instances." 6 | value = data.oci_core_instance.instances.*.private_ip 7 | } 8 | 9 | output "load_balancer_ip" { 10 | description = "The canonical IP address that the load balancer serves traffic from." 11 | value = var.create_load_balancer ? oci_load_balancer_load_balancer.lb[0].ip_address_details[0].ip_address : var.load_balancer_ip 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // Common OCI resource variables 5 | variable "availability_domain_id" { 6 | type = string 7 | description = "The ID of the availability domain inside the `region` in which to create this deployment" 8 | } 9 | 10 | variable "compartment_id" { 11 | type = string 12 | description = "The OCID of the compartment in which to create this deployment" 13 | } 14 | 15 | variable "prefix" { 16 | type = string 17 | description = "A unique prefix to attach to the name of all cloud resources that are created as a part of this deployment" 18 | } 19 | 20 | variable "instance_shape" { 21 | type = map(any) 22 | description = "The OCI instance shape to use for all compute resources that are created as part of this deployment" 23 | } 24 | 25 | variable "image_ocid" { 26 | type = string 27 | description = "The OCID of the OS image to use when creating all compute resources that are part of this deployment" 28 | } 29 | 30 | variable "subnet_id" { 31 | type = string 32 | description = "The OCID of a pre-existing subnet that all newly created cloud resources will be configured to use. If this variable to set to the empty string, a network configuration will be generated automatically" 33 | } 34 | 35 | // Compute instance specific variables 36 | variable "ssh_public_key_path" { 37 | type = string 38 | description = "The SSH public key path to use when configuring access to any compute resources created as part of this deployment" 39 | } 40 | variable "instance_user_data" { 41 | type = string 42 | description = "Raw cloud-init data that is to be used to instantiate new compute resources" 43 | } 44 | 45 | // Instance pool specific variables 46 | variable "pool_size" { 47 | type = number 48 | description = "The initial number of compute instances to spawn as part of this deployment" 49 | } 50 | 51 | // Load balancer specific variables 52 | variable "load_balancer_shape" { 53 | type = map(string) 54 | description = "The OCI shape of the load balancer to create to service this pool" 55 | } 56 | 57 | variable "load_balancer_policy" { 58 | type = string 59 | description = "The traffic policy to apply to the load balancer backend that represents this pool" 60 | default = "LEAST_CONNECTIONS" 61 | } 62 | 63 | variable "load_balancer_protocol" { 64 | type = string 65 | description = "The protocol that the load balancer listener listens for" 66 | default = "HTTP" 67 | } 68 | 69 | variable "load_balancer_port" { 70 | type = string 71 | description = "The port your application runs on. This port is used to create the load balancer listeners and to create the backends" 72 | } 73 | 74 | variable "load_balancer_ocid" { 75 | type = string 76 | description = "Optional OCID specifying an existing load balancer. If provided, no load balancer will be created and all other resources will be attached to this load balancer" 77 | default = "" 78 | } 79 | 80 | variable "create_load_balancer" { 81 | type = string 82 | description = "If true, automatically generate a load balancer. If false, do not generate one and an OCID must be provided instead" 83 | default = true 84 | } 85 | 86 | variable "load_balancer_ip" { 87 | type = string 88 | description = "If a custom load balancer is provided, this must be set to the canonical IP address that the load balancer serves traffic from" 89 | default = "" 90 | } 91 | 92 | variable "freeform_tags" { 93 | description = "Freeform tags with useful miscellaneous information." 94 | type = map(any) 95 | default = {} 96 | } 97 | -------------------------------------------------------------------------------- /modules/oci-ocne-autoscaling/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-compute/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # 28 | # !example_override.tf 29 | 30 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 31 | # example: *tfplan* 32 | 33 | ### JetBrains template 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | 104 | -------------------------------------------------------------------------------- /modules/oci-ocne-compute/README.md: -------------------------------------------------------------------------------- 1 | # oci-ocne-compute 2 | 3 | This module deploys a number of compute resources in the configured OCI tenant, region, compartment, and availability domain. It also will wait for any cloud-init scripts to finish before the module finishes, ensuring that anything consuming these instances can count on instantiation having completed. 4 | 5 | ## Getting Started 6 | 7 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 8 | -------------------------------------------------------------------------------- /modules/oci-ocne-compute/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | resource "oci_core_instance" "instance" { 5 | count = var.instance_count 6 | availability_domain = var.availability_domain_id 7 | compartment_id = var.compartment_id 8 | display_name = format("${var.prefix}-%03d", count.index + 1) 9 | freeform_tags = var.freeform_tags 10 | 11 | shape = lookup(var.instance_shape, "shape", "VM.Standard2.2") 12 | 13 | dynamic "shape_config" { 14 | for_each = length(regexall("Flex", lookup(var.instance_shape, "shape", "VM.Standard.E3.Flex"))) > 0 ? [1] : [] 15 | content { 16 | ocpus = max(1, lookup(var.instance_shape, "ocpus", 1)) 17 | memory_in_gbs = (lookup(var.instance_shape, "memory", 4) / lookup(var.instance_shape, "ocpus", 1)) > 64 ? (lookup(var.instance_shape, "ocpus", 1) * 16) : lookup(var.instance_shape, "memory", 4) 18 | } 19 | } 20 | 21 | source_details { 22 | source_type = "image" 23 | source_id = var.image_ocid 24 | boot_volume_size_in_gbs = lookup(var.instance_shape, "boot_volume_size", null) 25 | } 26 | 27 | connection { 28 | agent = false 29 | timeout = "10m" 30 | host = self.private_ip 31 | user = "opc" 32 | private_key = file(var.ssh_private_key_path) 33 | bastion_host = var.bastion_public_ip 34 | bastion_user = var.bastion_user 35 | bastion_private_key = var.enable_bastion || var.bastion_public_ip != "" ? file(var.bastion_private_key_path) : "" 36 | } 37 | 38 | create_vnic_details { 39 | assign_public_ip = "false" 40 | subnet_id = var.subnet_id 41 | hostname_label = format("${var.prefix}-%03d", count.index + 1) 42 | } 43 | 44 | metadata = { 45 | ssh_authorized_keys = file(var.ssh_public_key_path) 46 | } 47 | 48 | provisioner "file" { 49 | content = var.init_script 50 | destination = "/home/${var.compute_user}/ocne-init.sh" 51 | } 52 | 53 | provisioner "remote-exec" { 54 | inline = [ 55 | "set -x", 56 | "sudo bash /home/${var.compute_user}/ocne-init.sh" 57 | ] 58 | } 59 | } 60 | 61 | resource "oci_core_vnic_attachment" "second_vnic" { 62 | count = var.attach_secondary_vnic ? var.instance_count : 0 63 | instance_id = oci_core_instance.instance[count.index].id 64 | create_vnic_details { 65 | assign_public_ip = "false" 66 | # subnet_id = var.secondary_subnet_id 67 | subnet_id = var.subnet_id 68 | freeform_tags = var.freeform_tags 69 | } 70 | } 71 | 72 | data "oci_core_vnic" "second_vnic" { 73 | count = var.attach_secondary_vnic ? var.instance_count : 0 74 | vnic_id = oci_core_vnic_attachment.second_vnic[count.index].vnic_id 75 | } 76 | 77 | resource "null_resource" "assign_vnics" { 78 | count = var.attach_secondary_vnic ? var.instance_count : 0 79 | depends_on = [oci_core_vnic_attachment.second_vnic, data.oci_core_vnic.second_vnic] 80 | 81 | provisioner "remote-exec" { 82 | connection { 83 | agent = false 84 | timeout = "10m" 85 | host = oci_core_instance.instance[count.index].private_ip 86 | user = "opc" 87 | private_key = file(var.ssh_private_key_path) 88 | bastion_host = var.bastion_public_ip 89 | bastion_user = var.bastion_user 90 | bastion_private_key = var.enable_bastion || var.bastion_public_ip != "" ? file(var.bastion_private_key_path) : "" 91 | } 92 | inline = [ 93 | "set -x", 94 | "timeout 10m bash -c \"until (/sbin/ip addr | grep '${data.oci_core_vnic.second_vnic[count.index].private_ip_address}[^0-9]'); do sleep 2; sudo oci-network-config -a; done\"; sudo firewall-cmd --add-interface=ens5; sudo firewall-cmd --zone=public --change-interface=ens5", 95 | ] 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /modules/oci-ocne-compute/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "private_ip" { 5 | description = "Private IP address of instance." 6 | value = oci_core_instance.instance.*.private_ip 7 | } 8 | 9 | output "secondary_private_ip" { 10 | depends_on = [null_resource.assign_vnics] 11 | value = data.oci_core_vnic.second_vnic.*.private_ip_address 12 | } 13 | 14 | output "node_ocids" { 15 | description = "Comma separated list of Kubernetes nodes (both control plane and worker nodes) with their Oracle Cloud Identifiers (OCIDs)." 16 | value = oci_core_instance.instance.*.id 17 | } 18 | -------------------------------------------------------------------------------- /modules/oci-ocne-compute/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // Common OCI resource variables 5 | variable "availability_domain_id" { 6 | type = string 7 | description = "The ID of the availability domain inside the `region` in which to create this deployment" 8 | } 9 | 10 | variable "compartment_id" { 11 | type = string 12 | description = "The OCID of the compartment in which to create this deployment" 13 | } 14 | 15 | variable "prefix" { 16 | type = string 17 | description = "A unique prefix to attach to the name of all cloud resources that are created as a part of this deployment" 18 | } 19 | 20 | variable "instance_shape" { 21 | type = map(any) 22 | description = "The OCI instance shape to use for all compute resources that are created as part of this deployment" 23 | } 24 | 25 | variable "image_ocid" { 26 | type = string 27 | description = "The OCID of the OS image to use when creating all compute resources that are part of this deployment" 28 | } 29 | 30 | variable "subnet_id" { 31 | type = string 32 | description = "The OCID of a pre-existing subnet that all newly created cloud resources will be configured to use. If this variable to set to the empty string, a network configuration will be generated automatically" 33 | } 34 | 35 | variable "secondary_subnet_id" { 36 | type = string 37 | description = "The OCID of a pre-existing subnet. If non-empty, each instance created by this module will have a secondary VNIC assigned to this subnet and a private IP address within it will be allocated." 38 | default = "" 39 | } 40 | 41 | variable "attach_secondary_vnic" { 42 | type = bool 43 | description = "If set to true, allocate a secondary VNIC and attach it to the subnet identified bvy `secondary_subnet_id`" 44 | default = false 45 | } 46 | 47 | // Compute instance specific variables 48 | variable "ssh_public_key_path" { 49 | type = string 50 | description = "The SSH public key path to use when configuring access to any compute resources created as part of this deployment" 51 | } 52 | 53 | variable "ssh_private_key_path" { 54 | type = string 55 | description = "THe SSH private key path that goes with the SSH public key that is used when accessing compute resources that are created as part of this deployment" 56 | } 57 | 58 | variable "init_script" { 59 | type = string 60 | description = "Init script post instance creation" 61 | } 62 | 63 | variable "instance_count" { 64 | type = number 65 | description = "The number of compute instances to create with the given configuration" 66 | } 67 | 68 | variable "enable_bastion" { 69 | type = bool 70 | description = "Decides if bastion is installed. Intended for internal use. Set to false." 71 | } 72 | 73 | variable "bastion_public_ip" { 74 | type = string 75 | description = "Public IP address of the Bastion host" 76 | } 77 | 78 | variable "bastion_user" { 79 | type = string 80 | description = "User name on the Bastion host" 81 | default = "opc" 82 | } 83 | 84 | variable "bastion_private_key_path" { 85 | type = string 86 | description = "The location of the SSH private key for the Bastion host" 87 | } 88 | 89 | variable "compute_user" { 90 | type = string 91 | description = "A user configured with sudo access and authenticated with ssh_public_key_path and ssh_private_key_path on each compute resource" 92 | } 93 | 94 | variable "freeform_tags" { 95 | description = "Freeform tags with useful miscellaneous information." 96 | type = map(any) 97 | default = {} 98 | } 99 | -------------------------------------------------------------------------------- /modules/oci-ocne-compute/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-images/README.md: -------------------------------------------------------------------------------- 1 | # oci-ocne-images 2 | 3 | A terraform module that can select a specific OCI image from a given set. 4 | 5 | This module selects the latest image from the list generated by operating system and version from OCI. The `os` terraform variable corresponds to the same field in the OCI API query, as does the `os_version` variable. 6 | 7 | In addition to providing the latest image via the `image_ocid` output, this module exposes the entire list via `all_images` if the full list of images for a given operating system and version is desired. 8 | 9 | ## Getting Started 10 | 11 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 12 | -------------------------------------------------------------------------------- /modules/oci-ocne-images/datasources.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # Gets the OCID of the OS image to use 5 | data "oci_core_images" "OLImageOCID" { 6 | compartment_id = var.compartment_id 7 | operating_system = var.os 8 | operating_system_version = var.os_version 9 | sort_by = "TIMECREATED" 10 | sort_order = "DESC" 11 | 12 | # filter to avoid Oracle Linux images for GPU 13 | filter { 14 | name = "display_name" 15 | values = ["^${replace(var.os, " ", "-")}-${var.os_version}\\.?[0-9]?-[0-9][0-9][0-9][0-9].[0-9][0-9].[0-9][0-9]-[0-9]$"] 16 | regex = true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /modules/oci-ocne-images/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "image_ocid" { 5 | value = data.oci_core_images.OLImageOCID.images[0].id 6 | } 7 | 8 | output "all_images" { 9 | value = data.oci_core_images.OLImageOCID.images 10 | } 11 | -------------------------------------------------------------------------------- /modules/oci-ocne-images/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | variable "compartment_id" { 5 | } 6 | 7 | variable "os" { 8 | default = "Oracle Linux" 9 | } 10 | 11 | variable "os_version" { 12 | default = "7.8" 13 | } 14 | -------------------------------------------------------------------------------- /modules/oci-ocne-images/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # 28 | # !example_override.tf 29 | 30 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 31 | # example: *tfplan* 32 | 33 | ### JetBrains template 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | 104 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/README.md: -------------------------------------------------------------------------------- 1 | # oci-ocne-kms 2 | 3 | Optionally creates an OCI KMS Vault and OCI KMS Vault Key. If an existing vault or key is provided, they will be re-used. Note that an OCI KMS Vault is not the same thing as a Hashicorp Vault. In fact, the resources created by this module are typically consumed by the Hashicorp Vault module. 4 | 5 | Note that allowing this module to generate keys and vault will create resources in OCI that are subject to OCI retention policies. In particular, both of these objects will not be deleted until 30 days after they are destroyed. 6 | When testing this module or one that consumed it, it is usually a good idea to manually create these resources and pass them in. Otherwise it is very easy to hit the service limit for each type. 7 | 8 | ## Getting Started 9 | 10 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 11 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/datasources.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | data "oci_kms_vault" "vault" { 5 | count = length(var.vault_ocid) > 0 ? 1 : 0 6 | vault_id = var.vault_ocid 7 | } 8 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/locals.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | locals { 5 | vault_ocid = length(var.vault_ocid) > 0 ? data.oci_kms_vault.vault[0].id : oci_kms_vault.vault[0].id 6 | key_ocid = length(var.key_ocid) > 0 ? var.key_ocid : oci_kms_key.vault_key[0].id 7 | crypto_endpoint = length(var.vault_ocid) > 0 ? data.oci_kms_vault.vault[0].crypto_endpoint : oci_kms_vault.vault[0].crypto_endpoint 8 | management_endpoint = length(var.vault_ocid) > 0 ? data.oci_kms_vault.vault[0].management_endpoint : oci_kms_vault.vault[0].management_endpoint 9 | } 10 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | resource "oci_kms_vault" "vault" { 5 | count = length(var.vault_ocid) > 0 ? 0 : 1 6 | compartment_id = var.compartment_id 7 | display_name = "${var.prefix}-vault" 8 | vault_type = var.type 9 | 10 | # Optional 11 | freeform_tags = var.freeform_tags 12 | } 13 | 14 | resource "oci_kms_key" "vault_key" { 15 | count = length(var.key_ocid) > 0 ? 0 : 1 16 | compartment_id = var.compartment_id 17 | display_name = "${var.prefix}-vault-key" 18 | key_shape { 19 | algorithm = var.key_algorithm 20 | length = var.key_length 21 | } 22 | management_endpoint = local.management_endpoint 23 | 24 | # Optional 25 | freeform_tags = var.freeform_tags 26 | } 27 | 28 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "management_endpoint" { 5 | description = "OCI KMS vault management endpoint." 6 | value = local.management_endpoint 7 | } 8 | 9 | output "crypto_endpoint" { 10 | description = "OCI KMS vault crypto endpoint." 11 | value = local.crypto_endpoint 12 | } 13 | 14 | output "key_id" { 15 | description = "OCI KMS vault key id." 16 | value = local.key_ocid 17 | } 18 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // Common OCI resource variables 5 | variable "compartment_id" { 6 | type = string 7 | description = "The OCID of the compartment in which to create this deployment" 8 | } 9 | variable "vault_ocid" { 10 | type = string 11 | description = "The OCID of the OCI KMS Vault to use. If not provided, one will be created" 12 | } 13 | 14 | variable "prefix" { 15 | type = string 16 | description = "A unique prefix to attach to the name of all cloud resources that are created as a part of this deployment" 17 | } 18 | 19 | variable "type" { 20 | type = string 21 | description = "The type of OCI KMS Vault to instantiate" 22 | default = "DEFAULT" 23 | } 24 | 25 | variable "key_length" { 26 | type = number 27 | description = "The length of the OCI KMS Vault Key to generate, in bits" 28 | default = "16" 29 | } 30 | 31 | variable "key_algorithm" { 32 | type = string 33 | description = "The cryptographic algorithm used to generate the OCI KMS Vault Key" 34 | default = "AES" 35 | } 36 | 37 | variable "key_ocid" { 38 | type = string 39 | description = "The OCID of the OCI KMS Vault Key to use. If not provided, one will be created" 40 | default = "" 41 | } 42 | 43 | variable "freeform_tags" { 44 | description = "Freeform tags with useful miscellaneous information." 45 | type = map(any) 46 | default = {} 47 | } 48 | -------------------------------------------------------------------------------- /modules/oci-ocne-kms/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-loadbalancer/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # 28 | # !example_override.tf 29 | 30 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 31 | # example: *tfplan* 32 | 33 | ### JetBrains template 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | 104 | -------------------------------------------------------------------------------- /modules/oci-ocne-loadbalancer/README.md: -------------------------------------------------------------------------------- 1 | # oci-ocne-loadbalancer 2 | 3 | This module allocates a load balancer and configures it with a default listener, backend, and backend set. 4 | 5 | ## Getting Started 6 | 7 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 8 | -------------------------------------------------------------------------------- /modules/oci-ocne-loadbalancer/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | resource "oci_load_balancer_load_balancer" "kube_apiserver_lb" { 5 | compartment_id = var.compartment_id 6 | display_name = "${var.prefix}-lb" 7 | shape = lookup(var.shape, "shape") 8 | subnet_ids = [var.subnet_id] 9 | is_private = "true" 10 | count = var.instance_count 11 | 12 | # Optional 13 | dynamic "shape_details" { 14 | for_each = length(regexall("flexible", lookup(var.shape, "shape", "flexible"))) > 0 ? [1] : [] 15 | content { 16 | minimum_bandwidth_in_mbps = lookup(var.shape, "flex_min") 17 | maximum_bandwidth_in_mbps = lookup(var.shape, "flex_max") 18 | } 19 | } 20 | freeform_tags = var.freeform_tags 21 | } 22 | 23 | resource "oci_load_balancer_backend_set" "lb_backend" { 24 | health_checker { 25 | protocol = var.protocol 26 | port = var.port 27 | url_path = "/sys/health" 28 | } 29 | count = var.instance_count 30 | load_balancer_id = oci_load_balancer_load_balancer.kube_apiserver_lb[0].id 31 | name = "${var.prefix}-backend" 32 | policy = var.policy 33 | } 34 | 35 | // Please see the comment on the backend_count variable to 36 | // understand why this is done with count rather than for_each 37 | // and why there's a stupid lookup into backends variables. 38 | resource "oci_load_balancer_backend" "backends" { 39 | depends_on = [oci_load_balancer_backend_set.lb_backend] 40 | count = (var.instance_count > 0) ? var.backend_count : 0 41 | backendset_name = "${var.prefix}-backend" 42 | ip_address = keys(var.backends)[count.index] 43 | load_balancer_id = oci_load_balancer_load_balancer.kube_apiserver_lb[0].id 44 | port = var.backends[keys(var.backends)[count.index]] 45 | } 46 | 47 | resource "oci_load_balancer_listener" "listener" { 48 | depends_on = [oci_load_balancer_backend_set.lb_backend] 49 | default_backend_set_name = "${var.prefix}-backend" 50 | load_balancer_id = oci_load_balancer_load_balancer.kube_apiserver_lb[0].id 51 | name = "${var.prefix}-listener" 52 | port = var.port 53 | protocol = var.protocol 54 | count = var.instance_count 55 | } 56 | -------------------------------------------------------------------------------- /modules/oci-ocne-loadbalancer/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "ip_address" { 5 | description = "IP address of load balancer." 6 | value = var.instance_count > 0 ? oci_load_balancer_load_balancer.kube_apiserver_lb[0].ip_address_details[0].ip_address: "" 7 | } 8 | 9 | output "port" { 10 | description = "The port that the listener should serve traffic on" 11 | value = var.port 12 | } 13 | 14 | output "endpoint" { 15 | depends_on = [oci_load_balancer_listener.listener, oci_load_balancer_backend.backends] 16 | description = "Load balancer URI." 17 | value = var.instance_count > 0 ? "${oci_load_balancer_load_balancer.kube_apiserver_lb[0].ip_address_details[0].ip_address}:${var.port}" : "" 18 | } 19 | 20 | output "load_balancer_ocid" { 21 | description = "OCID of the load balancer." 22 | value = var.instance_count > 0 ? oci_load_balancer_load_balancer.kube_apiserver_lb[0].id : "" 23 | } 24 | -------------------------------------------------------------------------------- /modules/oci-ocne-loadbalancer/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // Common OCI resource variables 5 | variable "compartment_id" { 6 | type = string 7 | description = "The OCID of the compartment in which to create this deployment" 8 | } 9 | 10 | variable "prefix" { 11 | type = string 12 | description = "A unique prefix to attach to the name of all cloud resources that are created as a part of this deployment" 13 | } 14 | 15 | variable "subnet_id" { 16 | type = string 17 | description = "The OCID of a pre-existing subnet that all newly created cloud resources will be configured to use. If this variable to set to the empty string, a network configuration will be generated automatically" 18 | } 19 | 20 | // Load balancer specific variables 21 | variable "shape" { 22 | type = map(string) 23 | description = "The OCI shape of the load balancer to create" 24 | } 25 | 26 | variable "policy" { 27 | type = string 28 | description = "The traffic policy to apply to the load balancer backend set" 29 | default = "LEAST_CONNECTIONS" 30 | } 31 | 32 | variable "protocol" { 33 | type = string 34 | description = "The protocol that the listener create by this module listens on" 35 | default = "HTTP" 36 | } 37 | 38 | variable "port" { 39 | type = number 40 | description = "The port that the listener created by this module should serve traffic on" 41 | } 42 | 43 | variable "backends" { 44 | type = map(any) 45 | description = "A mapping of IP address or hostname to ports. These will become the backend set for the load balancer" 46 | } 47 | 48 | // While in most cases the length of the backend 49 | // map can be calculated appropriately, there are 50 | // cases where the backends are dynamically generated 51 | // by some calling module where the plan stage would 52 | // be unable determine the backends variable until 53 | // part of the apply has finished. Hence this 54 | // seemingly pointless argument. 55 | variable "backend_count" { 56 | type = number 57 | description = "The number of keys in the `backends` variable" 58 | } 59 | 60 | variable "freeform_tags" { 61 | description = "Freeform tags with useful miscellaneous information." 62 | type = map(any) 63 | default = {} 64 | } 65 | 66 | variable "instance_count" { 67 | type = number 68 | description = "The number of LB instances to create with the given configuration" 69 | } 70 | -------------------------------------------------------------------------------- /modules/oci-ocne-loadbalancer/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/oci-ocne-network/README.md: -------------------------------------------------------------------------------- 1 | # oci-ocne-vcn 2 | 3 | Terraform deployment of OCNE-specific VCN -------------------------------------------------------------------------------- /modules/oci-ocne-network/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # Modules and Resources 5 | module "vcn" { 6 | source = "oracle-terraform-modules/vcn/oci" 7 | version = "3.5.4" 8 | count = var.deploy_networking ? 1 : 0 9 | 10 | # Required 11 | compartment_id = var.compartment_id 12 | 13 | # Optional 14 | vcn_name = "${var.prefix}-vcn" 15 | vcn_dns_label = var.vcn_dns_label 16 | create_internet_gateway = true 17 | create_nat_gateway = true 18 | create_service_gateway = false 19 | vcn_cidrs = [var.vnc_cidr_block] 20 | freeform_tags = var.freeform_tags 21 | } 22 | 23 | resource "oci_core_subnet" "tf_vcn_private_subnet" { 24 | count = var.deploy_networking ? 1 : 0 25 | 26 | # Required 27 | compartment_id = var.compartment_id 28 | vcn_id = var.deploy_networking ? module.vcn[0].vcn_id : var.vcn_id 29 | cidr_block = var.vnc_private_subnet_cidr_block 30 | 31 | # Optional 32 | route_table_id = var.deploy_networking ? module.vcn[0].nat_route_id : var.nat_route_id 33 | dns_label = var.private_dns_label 34 | dhcp_options_id = oci_core_dhcp_options.tf_dhcp_options[0].id 35 | security_list_ids = [oci_core_security_list.tf_private_security_list[0].id] 36 | display_name = "${var.prefix}-private-subnet" 37 | freeform_tags = var.freeform_tags 38 | } 39 | 40 | resource "oci_core_security_list" "tf_private_security_list" { 41 | count = var.deploy_networking ? 1 : 0 42 | 43 | compartment_id = var.compartment_id 44 | vcn_id = var.deploy_networking ? module.vcn[0].vcn_id : var.vcn_id 45 | display_name = "${var.prefix}-sg-private-subnet" 46 | 47 | freeform_tags = var.freeform_tags 48 | 49 | egress_security_rules { 50 | stateless = false 51 | destination = "0.0.0.0/0" 52 | destination_type = "CIDR_BLOCK" 53 | protocol = "all" 54 | } 55 | 56 | ingress_security_rules { 57 | stateless = false 58 | source = var.vnc_cidr_block 59 | source_type = "CIDR_BLOCK" 60 | 61 | # Get protocol numbers from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml TCP is 6 62 | protocol = "6" 63 | tcp_options { 64 | min = 1 65 | max = 65535 66 | } 67 | } 68 | 69 | ingress_security_rules { 70 | stateless = false 71 | source = var.vnc_cidr_block 72 | source_type = "CIDR_BLOCK" 73 | 74 | # Get protocol numbers from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml UDP is 17 75 | protocol = "17" 76 | udp_options { 77 | min = 1 78 | max = 65535 79 | } 80 | } 81 | 82 | ingress_security_rules { 83 | stateless = false 84 | source = "0.0.0.0/0" 85 | source_type = "CIDR_BLOCK" 86 | # Get protocol numbers from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml ICMP is 1 87 | protocol = "1" 88 | 89 | # For ICMP type and code see: https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml 90 | icmp_options { 91 | type = 3 92 | code = 4 93 | } 94 | } 95 | 96 | ingress_security_rules { 97 | stateless = false 98 | source = var.vnc_cidr_block 99 | source_type = "CIDR_BLOCK" 100 | # Get protocol numbers from https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml ICMP is 1 101 | protocol = "1" 102 | 103 | # For ICMP type and code see: https://www.iana.org/assignments/icmp-parameters/icmp-parameters.xhtml 104 | icmp_options { 105 | type = 3 106 | } 107 | } 108 | } 109 | 110 | resource "oci_core_dhcp_options" "tf_dhcp_options" { 111 | count = var.deploy_networking ? 1 : 0 112 | 113 | # Required 114 | compartment_id = var.compartment_id 115 | vcn_id = var.deploy_networking ? module.vcn[0].vcn_id : var.vcn_id 116 | 117 | #Options for type are either "DomainNameServer" or "SearchDomain" 118 | options { 119 | type = "DomainNameServer" 120 | server_type = "VcnLocalPlusInternet" 121 | } 122 | 123 | # Optional 124 | display_name = "ocne-dhcp-options" 125 | freeform_tags = var.freeform_tags 126 | } 127 | 128 | -------------------------------------------------------------------------------- /modules/oci-ocne-network/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # Outputs 5 | output "vcn_id" { 6 | value = var.deploy_networking ? module.vcn[0].vcn_id : var.vcn_id 7 | } 8 | 9 | output "ig_route_id" { 10 | value = var.deploy_networking ? module.vcn[0].ig_route_id : var.ig_route_id 11 | } 12 | 13 | output "private_security_list_id" { 14 | value = var.deploy_networking ? oci_core_security_list.tf_private_security_list[*] : [] 15 | } 16 | 17 | output "private_subnet_id" { 18 | value = var.deploy_networking ? oci_core_subnet.tf_vcn_private_subnet[*] : [] 19 | } 20 | -------------------------------------------------------------------------------- /modules/oci-ocne-network/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | compartment_id = "/dev/null 2>&1 ; then 25 | version=$(yq --version | awk '{print $NF}' | sed 's/^v//') 26 | oldver=$(printf "${version}"'\n'"${yqMin}"'\n' | sort -V | head -n1) 27 | if [[ "${oldver}" != "${yqMin}" ]]; then 28 | ERR=`addErr "Require yq >= v${yqMin}"` 29 | fi 30 | else 31 | # echo "yq is not installed" >> debug.log 32 | ERR=`addErr "Require yq >= v${yqMin}"` 33 | fi 34 | 35 | function list_mods() { 36 | cat ${cfgFile} | yq eval '.environments[0].modules[].module' 37 | } 38 | 39 | function indexOf() { 40 | local mods=($(list_mods)) 41 | local idx=-1 42 | local found=false 43 | for mod in "${mods[@]}"; do 44 | idx=$(($idx + 1)) 45 | if [ "${mod}" == "$1" ]; then 46 | found=true 47 | echo $idx 48 | fi 49 | done 50 | if [ "${found}" == "false" ]; then 51 | echo -1 52 | fi 53 | } 54 | 55 | function nameOf() { 56 | yq e ".environments[0].modules[\"${1}\"].name" ${cfgFile} 57 | } 58 | 59 | function getArg() { 60 | local idx=$(indexOf ${1}) 61 | yq e ".environments[0].modules[\"${idx}\"].args.\"${2}\"" ${cfgFile} 62 | } 63 | 64 | function getFilePath() { 65 | filePath=$(getArg ${1} ${2}) 66 | if [ ${filePath} == null ]; then 67 | filePath="" 68 | else 69 | if [ -f "${filePath}" ]; then 70 | filePath="${filePath}" 71 | else 72 | filePath="The file of ${2} ${filePath} does not exist" 73 | fi 74 | fi 75 | echo "${filePath}" 76 | } 77 | 78 | ociKeyPath="" 79 | kvrtConfig="" 80 | if [[ -e ${cfgFile} ]]; then 81 | if [ "${envName}" != "myenvironment" ] && [ "${envName}" != "" ]; then 82 | ERR=`addErr "Remove variable environment_name=${envName} from terraform.tfvars"` 83 | fi 84 | if [ "${k8sName}" != "mycluster" ] && [ "${k8sName}" != "" ]; then 85 | ERR=`addErr "Remove variable kubernetes_name=${k8sName} from terraform.tfvars"` 86 | fi 87 | if [ "${ocneVer}" != "1.7" ] && [ "${ocneVer}" != "" ]; then 88 | ERR=`addErr "Remove variable ocne_version=${ocneVer} from terraform.tfvars"` 89 | fi 90 | numOfEnv=`yq eval '.environments | length' ${cfgFile}` 91 | if [[ "${numOfEnv}" != "1" ]]; then 92 | ERR=`addErr "config-file ${cfgFile} must have ONE environment"` 93 | fi 94 | mods=($(list_mods)) 95 | findK="" 96 | for mod in "${mods[@]}"; do 97 | if [ "${mod}" == "kubernetes" ]; then 98 | if [ "${findK}" != "" ]; then 99 | ERR=`addErr "config-file ${cfgFile} must have ONE kubernetes module"` 100 | fi 101 | findK="kubernetes" 102 | fi 103 | done 104 | if [ "${findK}" == "" ]; then 105 | ERR=`addErr "config-file ${cfgFile} must have ONE kubernetes module"` 106 | fi 107 | indexOfKube=$(indexOf kubernetes) 108 | envName=`yq eval '.environments[0].environment-name' ${cfgFile}` 109 | k8sName=$(nameOf ${indexOfKube}) 110 | ocneVer=`yq eval '.environments[0].globals.version' ${cfgFile}` 111 | if [ ${ocneVer} == null ]; then 112 | ocneVer="" 113 | fi 114 | ociKeyPath=$(getFilePath oci-ccm oci-private-key-file) 115 | if [[ "${ociKeyPath}" == *"does not exist" ]]; then 116 | ERR=`addErr "${ociKeyPath}"` 117 | ociKeyPath="" 118 | fi 119 | kvrtConfig=$(getFilePath kubevirt kubevirt-config) 120 | if [[ "${kvrtConfig}" == *"does not exist" ]]; then 121 | ERR=`addErr "${kvrtConfig}"` 122 | kvrtConfig="" 123 | fi 124 | else 125 | if [[ "${cfgFile}" != "" ]]; then 126 | ERR=`addErr "The file of config_file_path ${cfgFile} does not exist"` 127 | fi 128 | fi 129 | 130 | # echo "config-read ERR: ${ERR}" >> debug.log 131 | yq -o json < 25 | ---- 26 | 27 | This can be automatically added to pull requests by committing with: 28 | 29 | ---- 30 | git commit --signoff 31 | ---- 32 | 33 | Only pull requests from committers that can be verified as having 34 | signed the OCA can be accepted. 35 | 36 | === Pull request process 37 | 38 | . Fork this repository 39 | . Create a branch in your fork to implement the changes. We recommend using 40 | the issue number as part of your branch name, e.g. `1234-fixes` 41 | . Ensure that any documentation is updated with the changes that are required 42 | by your fix. 43 | . Ensure that any samples are updated if the base image has been changed. 44 | . Submit the pull request. *Do not leave the pull request blank*. Explain exactly 45 | what your changes are meant to do and provide simple steps on how to validate 46 | your changes. Ensure that you reference the issue you created as well. 47 | We will assign the pull request to 2-3 people for review before it is merged. -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/CONTRIBUTORS.adoc: -------------------------------------------------------------------------------- 1 | == GitHub userids of contributors 2 | 3 | OWNERS # have admin access and can merge code to master: 4 | 5 | - @hyder 6 | - @markxnelson 7 | 8 | CONTRIBUTORS 9 | 10 | - @karthicgit -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | 3 | The Universal Permissive License (UPL), Version 1.0 4 | 5 | Subject to the condition set forth below, permission is hereby granted to any 6 | person obtaining a copy of this software, associated documentation and/or data 7 | (collectively the "Software"), free of charge and under any and all copyright 8 | rights in the Software, and any and all patent rights owned or freely 9 | licensable by each licensor hereunder covering either (i) the unmodified 10 | Software as contributed to or provided by such licensor, or (ii) the Larger 11 | Works (as defined below), to deal in both 12 | 13 | (a) the Software, and 14 | (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if 15 | one is included with the Software (each a "Larger Work" to which the Software 16 | is contributed by such licensors), 17 | 18 | without restriction, including without limitation the rights to copy, create 19 | derivative works of, display, perform, and distribute the Software and make, 20 | use, sell, offer for sale, import, export, have made, and have sold the 21 | Software and the Larger Work(s), and to sublicense the foregoing rights on 22 | either these or other terms. 23 | 24 | This license is subject to the following condition: 25 | The above copyright notice and either this complete permission notice or at 26 | a minimum a reference to the UPL must be included in all copies or 27 | substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/README.adoc: -------------------------------------------------------------------------------- 1 | = Terraform Bastion for Oracle Cloud Infrastructure 2 | 3 | :idprefix: 4 | :idseparator: - 5 | 6 | :uri-repo: https://github.com/oracle-terraform-modules/terraform-oci-bastion 7 | 8 | :uri-rel-file-base: link:{uri-repo}/blob/master 9 | :uri-rel-tree-base: link:{uri-repo}/tree/master 10 | 11 | :uri-docs: {uri-rel-file-base}/docs 12 | 13 | :uri-changelog: {uri-rel-file-base}/CHANGELOG.adoc 14 | 15 | :uri-contribute: {uri-rel-file-base}/CONTRIBUTING.adoc 16 | :uri-contributors: {uri-rel-file-base}/CONTRIBUTORS.adoc 17 | 18 | :uri-license: {uri-rel-file-base}/LICENSE 19 | :uri-canonical-license: https://oss.oracle.com/licenses/upl/ 20 | :uri-networks-subnets-cidr: https://erikberg.com/notes/networks.html 21 | :uri-oci: https://cloud.oracle.com/cloud-infrastructure 22 | :uri-oci-documentation: https://docs.cloud.oracle.com/iaas/Content/home.htm 23 | :uri-oracle: https://www.oracle.com 24 | :uri-prereqs: {uri-docs}/prerequisites.adoc 25 | :uri-quickstart: {uri-docs}/quickstart.adoc 26 | :uri-reuse-module: {uri-rel-tree-base}/examples/ 27 | :uri-terraform: https://www.terraform.io 28 | :uri-terraform-cidrsubnet-deconstructed: http://blog.itsjustcode.net/blog/2017/11/18/terraform-cidrsubnet-deconstructed/ 29 | :uri-terraform-hashicorp-examples: https://github.com/hashicorp/terraform-guides/tree/master/infrastructure-as-code/terraform-0.12-examples 30 | :uri-terraform-oci: https://www.terraform.io/docs/providers/oci/index.html 31 | :uri-terraform-options: {uri-docs}/terraformoptions.adoc 32 | :uri-terraform-oci-examples: https://github.com/terraform-providers/terraform-provider-oci/tree/master/examples 33 | 34 | The {uri-repo}[Terraform OCI Bastion] for {uri-oci}[Oracle Cloud Infrastructure] (OCI) provides a Terraform module that reuses an existing VCN and adds a bastion host to it. 35 | 36 | It creates the following resources: 37 | 38 | * A configurable security list to allow ssh access from a defined CIDR block 39 | * A public subnet 40 | * A compute instance 41 | * An optional notification via email 42 | 43 | This module is primarily meant to be reusable to provide an entry point into your infrastructure on {uri-oci}[OCI]. 44 | You can further use it as part of higher level Terraform modules 45 | 46 | == {uri-docs}[Documentation] 47 | 48 | * {uri-prereqs}[Pre-requisites] 49 | 50 | * Instructions 51 | ** {uri-quickstart}[Quickstart] 52 | ** {uri-reuse-module}[Reusing as a Terraform module] 53 | * {uri-terraform-options}[Terraform Options] 54 | 55 | == Related Documentation, Blog 56 | * {uri-oci-documentation}[Oracle Cloud Infrastructure Documentation] 57 | * {uri-terraform-oci}[Terraform OCI Provider Documentation] 58 | * {uri-networks-subnets-cidr}[Erik Berg on Networks, Subnets and CIDR] 59 | * {uri-terraform-cidrsubnet-deconstructed}[Lisa Hagemann on Terraform cidrsubnet Deconstructed] 60 | 61 | == Projects using this module 62 | 63 | == Changelog 64 | 65 | View the {uri-changelog}[CHANGELOG]. 66 | 67 | == Acknowledgement 68 | 69 | Code derived and adapted from {uri-terraform-oci-examples}[Terraform OCI Examples] and Hashicorp's {uri-terraform-hashicorp-examples}[Terraform 0.12 examples] 70 | 71 | == Contributors 72 | 73 | {uri-contributors}[Folks who contributed with explanations, code, feedback, ideas, testing etc.] 74 | 75 | Learn how to {uri-contribute}[contribute]. 76 | 77 | == License 78 | 79 | Copyright(c) 2023 Oracle and/or its associates. All rights reserved. 80 | 81 | Licensed under the {uri-license}[Universal Permissive License 1.0] as shown at 82 | {uri-canonical-license}[https://oss.oracle.com/licenses/upl]. 83 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/README.md: -------------------------------------------------------------------------------- 1 | # Terraform OCI Bastion for Oracle Cloud Infrastructure 2 | 3 | [changelog]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/CHANGELOG.adoc 4 | [contributing]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/CONTRIBUTING.adoc 5 | [contributors]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/CONTRIBUTORS.adoc 6 | [docs]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/tree/master/docs 7 | 8 | [license]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/LICENSE 9 | [canonical_license]: https://oss.oracle.com/licenses/upl/ 10 | 11 | [oci]: https://cloud.oracle.com/cloud-infrastructure 12 | [oci_documentation]: https://docs.cloud.oracle.com/iaas/Content/home.htm 13 | 14 | [oracle]: https://www.oracle.com 15 | [prerequisites]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/docs/prerequisites.adoc 16 | 17 | [quickstart]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/docs/quickstart.adoc 18 | [repo]: https://github.com/oracle/terraform-oci-bastion 19 | [reuse]: https://github.com/oracle/terraform-oci-bastion/examples/db 20 | [subnets]: https://erikberg.com/notes/networks.html 21 | [terraform]: https://www.terraform.io 22 | [terraform_cidr_subnet]: http://blog.itsjustcode.net/blog/2017/11/18/terraform-cidrsubnet-deconstructed/ 23 | [terraform_hashircorp_examples]: https://github.com/hashicorp/terraform-guides/tree/master/infrastructure-as-code/terraform-0.12-examples 24 | [terraform_oci]: https://www.terraform.io/docs/providers/oci/index.html 25 | [terraform_options]: https://github.com/oracle-terraform-modules/terraform-oci-bastion/blob/master/docs/terraformoptions.adoc 26 | [terraform_oci_examples]: https://github.com/terraform-providers/terraform-provider-oci/tree/master/examples 27 | [terraform_oci_oke]: https://github.com/oracle-terraform-modules/terraform-oci-oke 28 | 29 | The [Terraform OCI Bastion][repo] for [Oracle Cloud Infrastructure][OCI] provides a [Terraform][terraform] module that reuses an existing VCN and adds a bastion host to it. 30 | 31 | It creates the following resources: 32 | 33 | * A configurable security list to allow ssh access from a defined CIDR block 34 | * A public subnet 35 | * A compute instance 36 | * An optional notification via email 37 | 38 | This module is primarily meant to be reusable to provide an entry point into your infrastructure on {uri-oci}[OCI]. 39 | You can further use it as part of higher level Terraform modules 40 | 41 | ## [Documentation][docs] 42 | 43 | ### [Pre-requisites][prerequisites] 44 | 45 | #### Instructions 46 | - [Quickstart][quickstart] 47 | - [Reusing as a Terraform module][reuse] 48 | - [Terraform Options][terraform_options] 49 | 50 | ## Related Documentation, Blog 51 | - [Oracle Cloud Infrastructure Documentation][oci_documentation] 52 | - [Terraform OCI Provider Documentation][terraform_oci] 53 | - [Erik Berg on Networks, Subnets and CIDR][subnets] 54 | - [Lisa Hagemann on Terraform cidrsubnet Deconstructed][terraform_cidr_subnet] 55 | 56 | ## Projects using this module 57 | 58 | ## Changelog 59 | 60 | View the [CHANGELOG][changelog]. 61 | 62 | ## Acknowledgement 63 | 64 | Code derived and adapted from [Terraform OCI Examples][terraform_oci_examples] and Hashicorp's [Terraform 0.12 examples][terraform_oci_examples] 65 | 66 | ## Contributors 67 | 68 | [Folks who contributed with explanations, code, feedback, ideas, testing etc.][contributors] 69 | 70 | Learn how to [contribute][contributing]. 71 | 72 | ## License 73 | 74 | Copyright (c) 2023 Oracle and/or its associates. All rights reserved. 75 | 76 | Licensed under the [Universal Permissive License 1.0][license] as shown at 77 | [https://oss.oracle.com/licenses/upl][canonical_license]. 78 | 79 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/cloudinit/autonomous.template.yaml: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | #cloud-config 5 | timezone: ${timezone} 6 | 7 | write_files: 8 | # setup script 9 | - path: "/root/bastion/notification.sh" 10 | permissions: "0700" 11 | encoding: "gzip+base64" 12 | content: | 13 | ${notification_sh_content} 14 | runcmd: 15 | - echo "Configuring running notification script..." 16 | - bash /root/bastion/notification.sh 17 | - touch /home/opc/bastion.finish -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/compute.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | resource "oci_core_instance" "bastion" { 5 | availability_domain = element(local.ad_names, (var.availability_domain - 1)) 6 | compartment_id = var.compartment_id 7 | 8 | # Optional 9 | freeform_tags = var.freeform_tags 10 | 11 | create_vnic_details { 12 | assign_public_ip = true 13 | display_name = var.prefix == "none" ? "bastion-vnic" : "${var.prefix}-bastion-vnic" 14 | hostname_label = "bastion" 15 | subnet_id = oci_core_subnet.bastion.id 16 | } 17 | 18 | display_name = var.prefix == "none" ? "bastion" : "${var.prefix}-bastion" 19 | 20 | launch_options { 21 | boot_volume_type = "PARAVIRTUALIZED" 22 | network_type = "PARAVIRTUALIZED" 23 | } 24 | 25 | # prevent the bastion from destroying and recreating itself if the image ocid changes 26 | lifecycle { 27 | ignore_changes = [source_details[0].source_id] 28 | } 29 | 30 | metadata = { 31 | ssh_authorized_keys = var.ssh_public_key != "" ? var.ssh_public_key : file(var.ssh_public_key_path) 32 | user_data = data.template_cloudinit_config.bastion.rendered 33 | } 34 | 35 | shape = lookup(var.bastion_shape, "shape", "VM.Standard.E2.2") 36 | 37 | dynamic "shape_config" { 38 | for_each = length(regexall("Flex", lookup(var.bastion_shape, "shape", "VM.Standard.E3.Flex"))) > 0 ? [1] : [] 39 | content { 40 | ocpus = max(1, lookup(var.bastion_shape, "ocpus", 1)) 41 | memory_in_gbs = (lookup(var.bastion_shape, "memory", 4) / lookup(var.bastion_shape, "ocpus", 1)) > 64 ? (lookup(var.bastion_shape, "ocpus", 1) * 4) : lookup(var.bastion_shape, "memory", 4) 42 | } 43 | } 44 | 45 | source_details { 46 | boot_volume_size_in_gbs = lookup(var.bastion_shape, "boot_volume_size", null) 47 | source_type = "image" 48 | source_id = local.bastion_image_id 49 | } 50 | 51 | timeouts { 52 | create = "60m" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/datasources.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | data "oci_identity_availability_domains" "ad_list" { 5 | compartment_id = var.tenancy_id 6 | } 7 | 8 | data "template_file" "ad_names" { 9 | count = length(data.oci_identity_availability_domains.ad_list.availability_domains) 10 | template = lookup(data.oci_identity_availability_domains.ad_list.availability_domains[count.index], "name") 11 | } 12 | 13 | data "oci_identity_tenancy" "tenancy" { 14 | tenancy_id = var.tenancy_id 15 | } 16 | 17 | # get the tenancy's home region 18 | data "oci_identity_regions" "home_region" { 19 | filter { 20 | name = "key" 21 | values = [data.oci_identity_tenancy.tenancy.home_region_key] 22 | } 23 | } 24 | 25 | data "oci_core_vcn" "vcn" { 26 | vcn_id = var.vcn_id 27 | } 28 | 29 | data "template_file" "autonomous_template" { 30 | template = file("${path.module}/scripts/notification.template.sh") 31 | 32 | vars = { 33 | enable_notification = var.enable_notification 34 | topic_id = var.enable_notification == true ? oci_ons_notification_topic.bastion_notification[0].topic_id : "null" 35 | } 36 | 37 | count = var.bastion_image_id == "Autonomous" ? 1 : 0 38 | } 39 | 40 | data "template_file" "autonomous_cloud_init_file" { 41 | template = file("${path.module}/cloudinit/autonomous.template.yaml") 42 | 43 | vars = { 44 | notification_sh_content = base64gzip(data.template_file.autonomous_template[0].rendered) 45 | timezone = var.timezone 46 | } 47 | 48 | count = var.bastion_image_id == "Autonomous" ? 1 : 0 49 | } 50 | 51 | data "oci_core_images" "autonomous_images" { 52 | compartment_id = var.compartment_id 53 | operating_system = "Oracle Autonomous Linux" 54 | shape = lookup(var.bastion_shape, "shape", "VM.Standard.E2.2") 55 | sort_by = "TIMECREATED" 56 | } 57 | 58 | # cloud init for bastion 59 | data "template_cloudinit_config" "bastion" { 60 | gzip = true 61 | base64_encode = true 62 | 63 | part { 64 | filename = "bastion.yaml" 65 | content_type = "text/cloud-config" 66 | content = data.template_file.autonomous_cloud_init_file[0].rendered 67 | } 68 | } 69 | 70 | # Gets a list of VNIC attachments on the bastion instance 71 | data "oci_core_vnic_attachments" "bastion_vnics_attachments" { 72 | availability_domain = element(local.ad_names, (var.availability_domain - 1)) 73 | compartment_id = var.compartment_id 74 | depends_on = [oci_core_instance.bastion] 75 | instance_id = oci_core_instance.bastion.id 76 | } 77 | 78 | # Gets the OCID of the first (default) VNIC on the bastion instance 79 | data "oci_core_vnic" "bastion_vnic" { 80 | depends_on = [oci_core_instance.bastion] 81 | vnic_id = lookup(data.oci_core_vnic_attachments.bastion_vnics_attachments.vnic_attachments[0], "vnic_id") 82 | } 83 | 84 | data "oci_core_instance" "bastion" { 85 | depends_on = [oci_core_instance.bastion] 86 | instance_id = oci_core_instance.bastion.id 87 | } 88 | 89 | data "oci_ons_notification_topic" "bastion_notification" { 90 | topic_id = oci_ons_notification_topic.bastion_notification[0].topic_id 91 | 92 | count = var.enable_notification ? 1 : 0 93 | } 94 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/docs/prerequisites.adoc: -------------------------------------------------------------------------------- 1 | = Pre-requisites 2 | 3 | :idprefix: 4 | :idseparator: - 5 | :sectlinks: 6 | 7 | :uri-repo: https://github.com/oracle-terraform-modules/terraform-oci-bastion 8 | 9 | :uri-rel-file-base: link:{uri-repo}/blob/master 10 | :uri-rel-tree-base: link:{uri-repo}/tree/master 11 | 12 | :uri-docs: {uri-rel-file-base}/docs 13 | 14 | :uri-oci: https://cloud.oracle.com/cloud-infrastructure 15 | :uri-oci-compartment: https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingcompartments.htm#two 16 | :uri-oci-ocids: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#five 17 | :uri-oci-documentation: https://docs.cloud.oracle.com/iaas/Content/home.htm 18 | :uri-oci-keys: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#two 19 | :uri-quickstart: {uri-docs}/quickstart.adoc 20 | :uri-terraform: https://www.terraform.io 21 | :uri-terraform-download: https://www.terraform.io/downloads.html 22 | 23 | This section will guide you through the pre-requisites before you can use this project. 24 | 25 | You can proceed to the {uri-quickstart}[Quick Start guide] if you have already done these. 26 | 27 | . link:#install-terraform[Install Terraform] 28 | .. link:#install-terraform-on-oracle-linux[Install Terraform on Oracle Linux] 29 | .. link:#install-terraform-on-macos[Install Terraform on macOS] 30 | .. link:#manual-installation[Manual Installation] 31 | ... link:#configure-path-on-linuxmacos[Configure path on Linux/macOS] 32 | ... link:#configure-path-on-windows[Configure path on Windows] 33 | .. link:#testing-terraform-installation[Testing Terraform installation] 34 | . link:#generate-and-upload-your-oci-api-keys[Generate and upload your OCI API keys] 35 | . link:#create-an-oci-compartment[Create an OCI Compartment] 36 | . link:#obtain-the-necessary-ocids[Obtain the necessary OCIDs] 37 | . link:#identity-and-access-management-rights[Identity and Access Management Rights] 38 | . link:#using-autonomous-linux[Using Autonomous Linux] 39 | 40 | === Install Terraform 41 | 42 | Start by installing Terraform and configuring your path. 43 | 44 | ==== Installing Terraform on Oracle Linux 45 | 46 | If you are using Oracle Linux, you can install Terraform as follows: 47 | 48 | [source,bash] 49 | ---- 50 | yum -y install oraclelinux-developer-release-el7 && yum -y install terraform 51 | ---- 52 | 53 | ==== Installing Terraform on macOS 54 | 55 | If you are using a Mac, you can install Terraform as follows: 56 | 57 | [source,bash] 58 | ---- 59 | brew install terraform 60 | ---- 61 | 62 | ==== Manual Installation 63 | 64 | If you prefer to install Terraform manually, you can follow these instructions: 65 | 66 | . Open your browser and navigate to the {uri-terraform-download}[Terraform download page]. You need version 0.12.24+. 67 | 68 | . Download the appropriate version for your operating system. 69 | 70 | . Extract the the contents of compressed file and copy the terraform binary to a location that is in your path (see next section below). 71 | 72 | . You will also need to configure your path. 73 | 74 | ===== Configure path on Linux/macOS 75 | 76 | Open a terminal and type the following: 77 | 78 | [source,bash] 79 | ---- 80 | sudo mv /path/to/terraform /usr/local/bin 81 | ---- 82 | 83 | ===== Configure path on Windows 84 | Follow the steps below to configure your path on Windows: 85 | 86 | . Click on 'Start', type 'Control Panel' and open it 87 | . Select System > Advanced System Settings > Environment Variables 88 | . Select System variables > PATH and click 'Edit' 89 | . Click New and paste the location of the directory where you have extracted the terraform.exe 90 | . Close all open windows by clicking 'OK' 91 | . Open a new terminal and verify terraform has been properly installed 92 | 93 | ==== Testing Terraform installation 94 | 95 | Open a terminal and test: 96 | 97 | [source,bash] 98 | ---- 99 | terraform -v 100 | Terraform v0.12.24 101 | ---- 102 | 103 | === Generate and upload your OCI API keys 104 | 105 | Follow the documentation for {uri-oci-keys}[generating and uploading your api keys]. 106 | 107 | Note the key fingerprint. 108 | 109 | === Create an OCI compartment 110 | 111 | Follow the documentation for {uri-oci-compartment}[creating a compartment]. 112 | 113 | === Obtain the necessary OCIDs 114 | 115 | The following OCIDs are required: 116 | 117 | . Compartment OCID 118 | . Tenancy OCID 119 | . User OCID 120 | 121 | Follow the documentation for {uri-oci-ocids}[obtaining the tenancy and user ocids]. 122 | 123 | To obtain the compartment OCID: 124 | 125 | 1. Navigate to Identity > Compartments 126 | 2. Click on your Compartment 127 | 3. Locate OCID on the page and click on 'Copy' -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/docs/quickstart.adoc: -------------------------------------------------------------------------------- 1 | = Quickstart 2 | 3 | :idprefix: 4 | :idseparator: - 5 | :sectlinks: 6 | 7 | 8 | :uri-repo: https://github.com/oracle-terraform-modules/terraform-oci-bastion 9 | :uri-rel-file-base: link:{uri-repo}/blob/master 10 | :uri-rel-tree-base: link:{uri-repo}/tree/master 11 | :uri-docs: {uri-rel-file-base}/docs 12 | :uri-oci-keys: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm 13 | :uri-oci-ocids: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm#five 14 | :uri-terraform: https://www.terraform.io 15 | :uri-terraform-oci: https://www.terraform.io/docs/providers/oci/index.html 16 | :uri-terraform-options: {uri-docs}/terraformoptions.adoc 17 | :uri-variables: {uri-rel-file-base}/variables.tf 18 | 19 | . link:#assumptions[Assumptions] 20 | . link:#pre-requisites[Pre-requisites] 21 | . link:#instructions[Instructions] 22 | . link:#related-documentation[Related documentation] 23 | 24 | === Assumptions 25 | 26 | 1. You have setup the {uri-oci-keys}[required keys] 27 | 2. You know the {uri-oci-ocids}[required OCIDs] 28 | 3. You have the necessary permissions 29 | 30 | === Pre-requisites 31 | 32 | 1. git is installed 33 | 2. ssh client is installed 34 | 3. Terraform 0.12.24+ is installed 35 | 36 | === Provisioning using this git repo 37 | 38 | . Clone the repo: 39 | 40 | + 41 | [source,bash] 42 | ---- 43 | git clone https://github.com/oracle-terraform-modules/terraform-oci-bastion.git tfbastion 44 | 45 | cd tfbastion 46 | 47 | cp terraform.tfvars.example terraform.tfvars 48 | ---- 49 | 50 | . Create a provider.tf file and add the following: 51 | 52 | + 53 | [source,hcl] 54 | ---- 55 | provider "oci" { 56 | tenancy_id = var.tenancy_id 57 | user_id = var.user_id 58 | fingerprint = var.fingerprint 59 | private_key_path = var.api_private_key_path 60 | region = var.region 61 | } 62 | ---- 63 | 64 | . Set mandatory provider parameters: 65 | 66 | * `fingerprint` 67 | * `api_private_key_path` 68 | * `region` 69 | * `tenancy_id` 70 | * `user_id` 71 | 72 | . Set other required parameters: 73 | 74 | * `compartment_id` 75 | * `prefix` 76 | * `ig_route_id` 77 | * `vcn_id` 78 | * 1 of `ssh_public_key` or `ssh_public_key_path` 79 | 80 | 81 | . Optional parameters to override: 82 | 83 | * `bastion_shape` 84 | * `bastion_upgrade` 85 | * `enable_notification` 86 | * `notification_endpoint` 87 | 88 | . Run Terraform: 89 | 90 | + 91 | [source,bash] 92 | ---- 93 | terraform init 94 | terraform plan 95 | terraform apply 96 | ---- 97 | 98 | === Related documentation: 99 | 100 | * {uri-terraform-options}[All Terraform configuration options] for {uri-repo}[this project] 101 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/docs/terraformoptions.adoc: -------------------------------------------------------------------------------- 1 | = Terraform Options 2 | :idprefix: 3 | :idseparator: - 4 | :sectlinks: 5 | :sectnums: 6 | :uri-repo: https://github.com/oracle-terraform-modules/terraform-oci-bastion 7 | 8 | :uri-rel-file-base: link:{uri-repo}/blob/master 9 | :uri-rel-tree-base: link:{uri-repo}/tree/master 10 | 11 | :uri-docs: {uri-rel-file-base}/docs 12 | :uri-oci-region: https://docs.cloud.oracle.com/iaas/Content/General/Concepts/regions.htm 13 | :uri-terraform-cidrsubnet: https://www.terraform.io/docs/configuration/functions/cidrsubnet.html 14 | 15 | Configuration Terraform Options: 16 | 17 | . link:#provider-and-identity[Provider and Identity] 18 | . link:#general-oci[General OCI] 19 | . link:#oci-networking[VCN] 20 | 21 | Ensure you review the {uri-terraform-dependencies}[dependencies]. 22 | 23 | == Provider and Identity 24 | 25 | [stripes=odd,cols="1d,4d,3a,3a", options=header,width="100%"] 26 | |=== 27 | |Parameter 28 | |Description 29 | |Values 30 | |Default 31 | 32 | |`fingerprint` 33 | |ssl fingerprint of api public key. *Required when configuring provider*. 34 | | 35 | |None 36 | 37 | |`api_private_key_path` 38 | |path to api private key. *Required when configuring provider*. 39 | | 40 | |None 41 | 42 | |`region` 43 | |Region where to provision the OKE cluster. {uri-oci-region}[List of regions]. *Required when configuring provider*. 44 | | 45 | |None 46 | 47 | |`tenancy_id` 48 | |Tenancy id of the user. *Required when configuring provider*. 49 | | 50 | |None 51 | 52 | |`user_id` 53 | |User's id. *Required when configuring provider*. 54 | | 55 | |None 56 | 57 | |=== 58 | 59 | == General OCI 60 | 61 | [stripes=odd,cols="1d,4d,3a,3a", options=header,width="100%"] 62 | |=== 63 | |Parameter 64 | |Description 65 | |Values 66 | |Default 67 | 68 | |`compartment_id` 69 | |Compartment id where the VCN Cluster will be provisioned. *Required*. 70 | | 71 | |None 72 | 73 | |`prefix` 74 | |a string to be prepended to the name of resources. *Required*. 75 | | 76 | |None 77 | 78 | 79 | |=== 80 | 81 | == Network Parameters 82 | 83 | [stripes=odd,cols="1d,4d,3a,3a", options=header,width="100%"] 84 | |=== 85 | |Parameter 86 | |Description 87 | |Values 88 | |Default 89 | 90 | |`availability_domain` 91 | |the AD to place the bastion host 92 | | 1 93 | |1 94 | 95 | |`bastion_access` 96 | |CIDR block in the form of a string to which ssh access to the bastion must be restricted to. *_ANYWHERE_* is equivalent to 0.0.0.0/0 and allows ssh access from anywhere. 97 | |ANYWHERE or a cidr block such as XXX.XXX.XXX.XXX/YY 98 | |ANYWHERE 99 | 100 | |`ig_route_id` 101 | |the route id to the internet gateway of the VCN 102 | | 103 | | 104 | 105 | |`netnum` 106 | |0-based index of the bastion subnet when the VCN's CIDR is masked with the corresponding newbit value. 107 | | 108 | |32 109 | 110 | |`newbits` 111 | |The difference between the VCN's netmask and the desired bastion subnet mask. 112 | | 113 | |13 114 | 115 | |`vcn_id` 116 | |The id of the VCN to use when creating the bastion resources. *Required* 117 | | 118 | |None 119 | 120 | |=== 121 | 122 | == Bastion Host Parameters 123 | 124 | [stripes=odd,cols="1d,4d,3a,3a", options=header,width="100%"] 125 | |=== 126 | |Parameter 127 | |Description 128 | |Values 129 | |Default 130 | 131 | |`enable_bastion` 132 | |whether to create the bastion 133 | | true/false 134 | |true 135 | 136 | |`bastion_image_id` 137 | |Provide a custom image id for the bastion host or leave as Autonomous. 138 | |imageid/Autonomous 139 | |Autonomous 140 | 141 | |`bastion_shape` 142 | |The shape of bastion instance. This is now specified as a map and supports E3.Flex. If a non-Flex shape is specified, then the other parameters are ignored. 143 | |e.g. `bastion_shape = { 144 | shape="VM.Standard.E3.Flex", 145 | ocpus=1, 146 | memory=4, 147 | boot_volume_size=50 148 | }` 149 | |`bastion_shape = { 150 | shape="VM.Standard.E3.Flex", 151 | ocpus=1, 152 | memory=4, 153 | boot_volume_size=50 154 | }` 155 | 156 | |`bastion_upgrade` 157 | |Whether to upgrade the bastion host packages after provisioning. It's useful to set this to false during development/testing so the bastion is provisioned faster. 158 | |true/false 159 | |true 160 | 161 | |`ssh_public_key` 162 | |the content of the ssh public key used to access the bastion. set this or the ssh_public_key_path 163 | | 164 | |"" 165 | 166 | |`ssh_public_key_path` 167 | |path to the ssh public key used to access the bastion. set this or the ssh_public_key 168 | |"" 169 | | 170 | 171 | |`timezone` 172 | |The preferred timezone for the bastion host. {uri-timezones}[List of timezones] 173 | |e.g. Australia/Sydney 174 | |The preferred timezone for the bastion host. {uri-timezones}[List of timezones] 175 | 176 | |=== 177 | 178 | 179 | == Notification Parameters 180 | 181 | [stripes=odd,cols="1d,4d,3a,3a", options=header,width="100%"] 182 | |=== 183 | |Parameter 184 | |Description 185 | |Values 186 | |Default 187 | 188 | |`enable_notification` 189 | |Whether to enable ONS notification for the bastion host. 190 | |true/false 191 | |false 192 | 193 | |`notification_endpoint` 194 | |The subscription notification endpoint. Email address to be notified. *Required if enable_notification = true* .. 195 | | 196 | |Autonomous 197 | 198 | |`notification_protocol` 199 | |The notification protocol used. 200 | | 201 | |EMAIL 202 | 203 | |`notification_topic` 204 | |The name of the notification topic. 205 | | 206 | |bastion 207 | |=== 208 | 209 | == Tagging Parameters 210 | 211 | [stripes=odd,cols="1d,4d,3a,3a", options=header,width="100%"] 212 | |=== 213 | |Parameter 214 | |Description 215 | |Values 216 | |Default 217 | 218 | |`tags` 219 | |Freeform tags for bastion. 220 | | 221 | | 222 | [source] 223 | ---- 224 | tags = { 225 | department = "finance" 226 | environment = "dev" 227 | role = "bastion" 228 | } 229 | ---- -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/examples/README.md: -------------------------------------------------------------------------------- 1 | [rootvariables]:https://github.com/oracle/terraform-oci-bastion/blob/master/examples/db/variables.tf 2 | [rootlocals]:https://github.com/oracle/terraform-oci-bastion/blob/master/examples/db/locals.tf 3 | [terraformoptions]:https://github.com/oracle/terraform-oci-bastion/blob/master/docs/terraformoptions.adoc 4 | 5 | Example reusing terraform-oci-bastion and extending to create other network resources. 6 | 7 | __Note: This is an example to demonstrate reusing this Terraform module to create additional network resources. Ensure you evaluate your own security needs when creating security lists, network security groups etc.__ 8 | 9 | ## Create a new Terraform project 10 | 11 | As an example, we’ll be using terraform-oci-bastion to create 12 | additional network resources in the VCN. The steps required are the following: 13 | 14 | 1. Create a new directory for your project e.g. mybastion 15 | 16 | 2. Create the following files in root directory of your project: 17 | 18 | - `variables.tf` 19 | - `locals.tf` 20 | - `provider.tf` 21 | - `main.tf` 22 | - `terraform.tfvars` 23 | 24 | 3. Define the oci provider 25 | 26 | ``` 27 | provider "oci" { 28 | tenancy_id = var.tenancy_id 29 | user_id = var.user_id 30 | fingerprint = var.fingerprint 31 | private_key_path = var.api_private_key_path 32 | region = var.region 33 | disable_auto_retries = false 34 | } 35 | ``` 36 | 37 | 4. Create the modules directory 38 | 39 | ``` 40 | mkdir modules 41 | cd modules 42 | ``` 43 | 44 | 5. Add the terraform-oci-bastion module 45 | 46 | ``` 47 | git clone https://github.com/oracle/terraform-oci-bastion.git bastion 48 | ``` 49 | 50 | Note: Cloning will be required until the module is published in HashiCorp's registry. 51 | 52 | ## Define project variables 53 | 54 | ### Variables to reuse the vcn module 55 | 56 | 1. Define the vcn parameters in the root `variables.tf`. 57 | See [`variables.tf`][rootvariables] in this directory. 58 | 59 | 2. Add additional variables if you need to. 60 | 61 | ## Define your modules 62 | 63 | 1. Define the bastion module in root `main.tf` 64 | 65 | ``` 66 | module "vcn" { 67 | source = "./modules/vcn" 68 | 69 | # general oci parameters 70 | compartment_id = var.compartment_id 71 | prefix = var.prefix 72 | 73 | # vcn parameters 74 | ig_route_id = var.ig_route_id 75 | vcn_id = var.vcn_id 76 | ssh_public_key = var.ssh_public_key 77 | } 78 | ``` 79 | 80 | 2. Enter appropriate values for `terraform.tfvars`. Review [Terraform Options][terraformoptions] for reference 81 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/examples/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | module "bastion" { 5 | source = "../" 6 | 7 | # general oci parameters 8 | 9 | compartment_id = "" 10 | 11 | prefix = "dev" 12 | 13 | # network parameters 14 | ig_route_id = "" 15 | 16 | vcn_id = "" 17 | 18 | ssh_public_key = "" 19 | } 20 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/examples/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # provider identity parameters 5 | 6 | fingerprint = "" 7 | 8 | api_private_key_path = "" 9 | 10 | region = "us-phoenix-1" 11 | 12 | tenancy_id = "" 13 | 14 | user_id = "" 15 | 16 | # general oci parameters 17 | 18 | compartment_id = "" 19 | 20 | prefix = "dev" 21 | 22 | # vcn parameters 23 | ig_route_id = "" 24 | 25 | vcn_id = "" 26 | 27 | ssh_public_key = "false" -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/examples/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # provider identity parameters 5 | variable "fingerprint" { 6 | description = "fingerprint of oci api private key" 7 | type = string 8 | default = "" 9 | } 10 | 11 | variable "api_private_key_path" { 12 | description = "path to oci api private key used" 13 | type = string 14 | default = "" 15 | } 16 | 17 | variable "region" { 18 | # List of regions: https://docs.cloud.oracle.com/iaas/Content/General/Concepts/regions.htm#ServiceAvailabilityAcrossRegions 19 | description = "the oci region where resources will be created" 20 | type = string 21 | } 22 | 23 | variable "tenancy_id" { 24 | description = "tenancy id where to create the sources" 25 | type = string 26 | } 27 | 28 | variable "user_id" { 29 | description = "id of user that terraform will use to create the resources" 30 | type = string 31 | } 32 | 33 | # general oci parameters 34 | 35 | variable "compartment_id" { 36 | description = "compartment id where to create all resources" 37 | type = string 38 | } 39 | 40 | variable "prefix" { 41 | description = "a string that will be prepended to all resources" 42 | type = string 43 | default = "none" 44 | } 45 | 46 | # bastion module parameters 47 | 48 | variable "ig_route_id" { 49 | type = string 50 | } 51 | 52 | variable "vcn_id" { 53 | type = string 54 | } 55 | 56 | variable "ssh_public_key" { 57 | type = string 58 | } 59 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/locals.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | # Protocols are specified as protocol numbers. 5 | # https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml 6 | 7 | locals { 8 | all_protocols = "all" 9 | ad_names = data.template_file.ad_names.*.rendered 10 | anywhere = "0.0.0.0/0" 11 | ssh_port = 22 12 | tcp_protocol = 6 13 | bastion_image_id = var.bastion_image_id == "Autonomous" ? data.oci_core_images.autonomous_images.images.0.id : var.bastion_image_id 14 | vcn_cidr = data.oci_core_vcn.vcn.cidr_block 15 | } 16 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/ons.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | resource "oci_ons_notification_topic" "bastion_notification" { 5 | compartment_id = var.compartment_id 6 | name = var.prefix == "none" ? var.notification_topic : "${var.prefix}-${var.notification_topic}" 7 | 8 | count = var.enable_notification ? 1 : 0 9 | 10 | freeform_tags = var.freeform_tags 11 | } 12 | 13 | resource "oci_ons_subscription" "bastion_notification" { 14 | compartment_id = var.compartment_id 15 | endpoint = var.notification_endpoint 16 | protocol = var.notification_protocol 17 | topic_id = oci_ons_notification_topic.bastion_notification[0].topic_id 18 | 19 | count = var.enable_notification ? 1 : 0 20 | 21 | freeform_tags = var.freeform_tags 22 | } 23 | 24 | resource "oci_identity_dynamic_group" "bastion_notification" { 25 | compartment_id = var.tenancy_id 26 | depends_on = [oci_core_instance.bastion] 27 | description = "dynamic group to allow bastion to send notifications to ONS" 28 | matching_rule = "ALL {instance.id = '${join(",", data.oci_core_instance.bastion.*.id)}'}" 29 | name = var.prefix == "none" ? "bastion-notification" : "${var.prefix}-bastion-notification" 30 | 31 | count = var.enable_notification ? 1 : 0 32 | 33 | freeform_tags = var.freeform_tags 34 | } 35 | 36 | resource "oci_identity_policy" "bastion_notification" { 37 | compartment_id = var.compartment_id 38 | depends_on = [oci_core_instance.bastion] 39 | description = "policy to allow bastion host to publish messages to ONS" 40 | name = var.prefix == "none" ? "bastion-notification" : "${var.prefix}-bastion-notification" 41 | statements = ["Allow dynamic-group ${oci_identity_dynamic_group.bastion_notification[0].name} to use ons-topic in compartment id ${var.compartment_id} where request.permission='ONS_TOPIC_PUBLISH'"] 42 | 43 | count = var.enable_notification ? 1 : 0 44 | 45 | freeform_tags = var.freeform_tags 46 | } 47 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/outputs.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "bastion_public_ip" { 5 | value = join(",", data.oci_core_vnic.bastion_vnic.*.public_ip_address) 6 | } -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/scripts/notification.template.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 4 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 5 | 6 | if [ ${enable_notification} ]; then 7 | sudo al-config -T ${topic_id} 8 | else 9 | echo 'ONS notification not enabled' 10 | fi -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/security.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | resource "oci_core_security_list" "bastion" { 5 | compartment_id = var.compartment_id 6 | display_name = var.prefix == "none" ? "bastion" : "${var.prefix}-bastion" 7 | freeform_tags = var.freeform_tags 8 | 9 | egress_security_rules { 10 | protocol = local.all_protocols 11 | destination = local.anywhere 12 | } 13 | 14 | ingress_security_rules { 15 | # allow ssh 16 | protocol = local.tcp_protocol 17 | source = var.bastion_access == "ANYWHERE" ? local.anywhere : var.bastion_access 18 | 19 | tcp_options { 20 | min = local.ssh_port 21 | max = local.ssh_port 22 | } 23 | } 24 | vcn_id = var.vcn_id 25 | } 26 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/subnets.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ 3 | 4 | resource "oci_core_subnet" "bastion" { 5 | cidr_block = cidrsubnet(local.vcn_cidr, var.newbits, var.netnum) 6 | compartment_id = var.compartment_id 7 | display_name = var.prefix == "none" ? "bastion" : "${var.prefix}-bastion" 8 | dns_label = "bastion" 9 | freeform_tags = var.freeform_tags 10 | prohibit_public_ip_on_vnic = false 11 | route_table_id = var.ig_route_id 12 | security_list_ids = [oci_core_security_list.bastion.id] 13 | vcn_id = var.vcn_id 14 | } 15 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # provider identity parameters 5 | 6 | fingerprint = "" 7 | 8 | api_private_key_path = "" 9 | 10 | region = "us-phoenix-1" 11 | 12 | tenancy_id = "" 13 | 14 | user_id = "" 15 | 16 | # general oci parameters 17 | 18 | compartment_id = "" 19 | 20 | prefix = "dev" 21 | 22 | # network parameters 23 | 24 | availability_domain = 1 25 | 26 | bastion_access = "ANYWHERE" 27 | 28 | ig_route_id = "" 29 | 30 | netnum = 32 31 | 32 | newbits = 13 33 | 34 | vcn_id = "" 35 | 36 | enable_bastion = true 37 | 38 | bastion_image_id = "Autonomous" 39 | 40 | bastion_shape = { 41 | # shape = "VM.Standard.E2.2" 42 | shape="VM.Standard.E3.Flex", 43 | ocpus=1, 44 | memory=4, 45 | boot_volume_size=50 46 | } 47 | 48 | bastion_upgrade = false 49 | 50 | ssh_public_key = "" 51 | 52 | ssh_public_key_path = "" 53 | 54 | # notification 55 | 56 | enable_notification = false 57 | 58 | notification_endpoint = "" 59 | 60 | notification_protocol = "EMAIL" 61 | 62 | notification_topic = "bastion" 63 | 64 | tags = { 65 | department = "finance" 66 | environment = "dev" 67 | role = "bastion" 68 | } 69 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # provider identity parameters 5 | variable "tenancy_id" { 6 | description = "tenancy id where to create the sources" 7 | type = string 8 | default = "" 9 | } 10 | 11 | # general oci parameters 12 | 13 | variable "compartment_id" { 14 | description = "compartment id where to create all resources" 15 | type = string 16 | } 17 | 18 | variable "prefix" { 19 | description = "a string that will be prepended to all resources" 20 | type = string 21 | default = "none" 22 | } 23 | 24 | # network parameters 25 | 26 | variable "availability_domain" { 27 | description = "the AD to place the bastion host" 28 | default = 1 29 | type = number 30 | } 31 | 32 | variable "bastion_access" { 33 | description = "CIDR block in the form of a string to which ssh access to the bastion must be restricted to. *_ANYWHERE_* is equivalent to 0.0.0.0/0 and allows ssh access from anywhere." 34 | default = "ANYWHERE" 35 | type = string 36 | } 37 | 38 | variable "ig_route_id" { 39 | description = "the route id to the internet gateway" 40 | type = string 41 | } 42 | 43 | variable "netnum" { 44 | description = "0-based index of the bastion subnet when the VCN's CIDR is masked with the corresponding newbit value." 45 | default = 32 46 | type = number 47 | } 48 | 49 | variable "newbits" { 50 | description = "The difference between the VCN's netmask and the desired bastion subnet mask" 51 | default = 13 52 | type = number 53 | } 54 | 55 | variable "vcn_id" { 56 | description = "The id of the VCN to use when creating the bastion resources." 57 | type = string 58 | } 59 | 60 | # bastion host parameters 61 | 62 | variable "bastion_image_id" { 63 | description = "Provide a custom image id for the bastion host or leave as Autonomous." 64 | default = "Autonomous" 65 | type = string 66 | } 67 | 68 | variable "bastion_shape" { 69 | description = "The shape of bastion instance." 70 | type = map(any) 71 | } 72 | 73 | variable "bastion_upgrade" { 74 | description = "Whether to upgrade the bastion host packages after provisioning. It's useful to set this to false during development/testing so the bastion is provisioned faster." 75 | default = false 76 | type = bool 77 | } 78 | 79 | variable "ssh_public_key" { 80 | description = "the content of the ssh public key used to access the bastion. set this or the ssh_public_key_path" 81 | default = "" 82 | type = string 83 | } 84 | 85 | variable "ssh_public_key_path" { 86 | description = "path to the ssh public key used to access the bastion. set this or the ssh_public_key" 87 | default = "" 88 | type = string 89 | } 90 | 91 | variable "timezone" { 92 | description = "The preferred timezone for the bastion host." 93 | default = "Australia/Sydney" 94 | type = string 95 | } 96 | 97 | # bastion notification 98 | 99 | variable "enable_notification" { 100 | description = "Whether to enable ONS notification for the bastion host." 101 | type = bool 102 | } 103 | 104 | variable "notification_endpoint" { 105 | description = "The subscription notification endpoint. Email address to be notified." 106 | default = null 107 | type = string 108 | } 109 | 110 | variable "notification_protocol" { 111 | description = "The notification protocol used." 112 | default = "EMAIL" 113 | type = string 114 | } 115 | 116 | variable "notification_topic" { 117 | description = "The name of the notification topic" 118 | default = "bastion" 119 | type = string 120 | } 121 | 122 | # tagging 123 | variable "freeform_tags" { 124 | description = "Freeform tags with useful miscellaneous information." 125 | type = map(any) 126 | default = {} 127 | } 128 | -------------------------------------------------------------------------------- /modules/terraform-oci-bastion/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # 28 | # !example_override.tf 29 | 30 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 31 | # example: *tfplan* 32 | 33 | ### JetBrains template 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | 104 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/README.md: -------------------------------------------------------------------------------- 1 | # terraform-oci-ocne-infrastructure 2 | 3 | This module deploys all OCI resources required for the OCNE Platform as well as any OCNE Modules. It accepts a cloud-init script from any callers that can be used to configure the nodes that will host 4 | OCNE Agents as well as nodes that will host OCNE API Servers. Aside from these options, this module performs no OCNE-specific configuration or setup. 5 | 6 | ## Getting Started 7 | 8 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 9 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/files/agent_init.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 4 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 5 | 6 | sudo dd iflag=direct if=/dev/oracleoci/oraclevda of=/dev/null count=1 7 | echo "1" | sudo tee /sys/class/block/`readlink /dev/oracleoci/oraclevda | cut -d'/' -f 2`/device/rescan 8 | sudo /usr/libexec/oci-growfs -y 9 | 10 | if [[ ${os_version} > 7.9 ]]; then 11 | if [[ ${yum_repo_url} != *"yum.oracle.com"* ]]; then 12 | dnf config-manager --add-repo ${yum_repo_url} 13 | fi 14 | else 15 | if [[ ${yum_repo_url} != *"yum.oracle.com"* ]]; then 16 | yum-config-manager --add-repo ${yum_repo_url} 17 | fi 18 | fi 19 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/files/apiserver_init.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 4 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 5 | 6 | sudo dd iflag=direct if=/dev/oracleoci/oraclevda of=/dev/null count=1 7 | echo "1" | sudo tee /sys/class/block/`readlink /dev/oracleoci/oraclevda | cut -d'/' -f 2`/device/rescan 8 | sudo /usr/libexec/oci-growfs -y 9 | 10 | if [[ ${os_version} > 7.9 ]]; then 11 | if [[ ${yum_repo_url} != *"yum.oracle.com"* ]]; then 12 | dnf config-manager --add-repo ${yum_repo_url} 13 | fi 14 | else 15 | if [[ ${yum_repo_url} != *"yum.oracle.com"* ]]; then 16 | yum-config-manager --add-repo ${yum_repo_url} 17 | fi 18 | fi 19 | 20 | function getPackageSuffix() { 21 | packageSuffix="${ocne_version}" 22 | if [[ $(echo $${packageSuffix} | awk -F'.' '{print NF}') -lt 3 ]]; then 23 | packageSuffix="" 24 | fi 25 | if [[ $(echo $${packageSuffix} | awk -F'-' '{print NF}') -gt 1 ]]; then 26 | if [[ "$${packageSuffix}" != *".el7" ]] && [[ "$${packageSuffix}" != *".el8" ]] && [[ "$${packageSuffix}" != *".el9" ]] ; then 27 | if [[ $(cat /etc/oracle-release) == "Oracle Linux Server release 9."* ]]; then 28 | packageSuffix="$${packageSuffix}.el9" 29 | elif [[ $(cat /etc/oracle-release) == "Oracle Linux Server release 8."* ]]; then 30 | packageSuffix="$${packageSuffix}.el8" 31 | else 32 | packageSuffix="$${packageSuffix}.el7" 33 | fi 34 | fi 35 | fi 36 | if [[ "$${packageSuffix}" != "" ]]; then 37 | packageSuffix="-$${packageSuffix}" 38 | fi 39 | echo $${packageSuffix} 40 | } 41 | 42 | # install olcnectl on api-server 43 | if [[ ${os_version} > 8.9 ]]; then 44 | dnf install -y oracle-olcne-release-el9 45 | dnf config-manager --disable ol9_olcne* 46 | dnf config-manager --enable ol9_olcne${ocne_short_version} ol9_addons ol9_baseos_latest 47 | packageSuffix=$(getPackageSuffix) 48 | dnf install -y olcnectl$${packageSuffix} 49 | elif [[ ${os_version} > 7.9 && ${os_version} < 9 ]]; then 50 | dnf install -y oracle-olcne-release-el8 51 | dnf config-manager --disable ol8_olcne* ol8_UEKR* 52 | dnf config-manager --enable ol8_olcne${ocne_short_version} ol8_addons ol8_baseos_latest ${kernel_version} 53 | packageSuffix=$(getPackageSuffix) 54 | dnf install -y olcnectl$${packageSuffix} 55 | else 56 | yum install -y oracle-olcne-release-el7 57 | yum-config-manager --disable ol7_olcne* 58 | yum-config-manager --enable ol7_olcne${ocne_short_version} ol7_kvm_utils ol7_addons ol7_latest 59 | packageSuffix=$(getPackageSuffix) 60 | yum install -y olcnectl$${packageSuffix} 61 | fi 62 | 63 | # prepare SSH keys on api-server 64 | ssh-keygen -q -N "" -f /home/${compute_user}/.ssh/id_rsa -C "${compute_user}@api-server-001" 65 | chown ${compute_user}: /home/${compute_user}/.ssh/id_rsa* 66 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/locals.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | locals { 5 | control_plane_nodes = contains(keys(module.control-plane-compute), "private_ip") ? (var.standalone_api_server ? flatten(module.control-plane-compute.private_ip) : flatten(concat(module.api-server-compute.private_ip, module.control-plane-compute.private_ip))) : [] 6 | apiserver_ip = contains(keys(module.api-server-compute), "private_ip") ? element(module.api-server-compute.private_ip, 0) : "" 7 | agents = flatten(concat(module.control-plane-compute.private_ip, module.worker-compute.private_ip)) 8 | all_nodes = distinct(concat([local.apiserver_ip], local.control_plane_nodes, local.agents)) 9 | total_nodes = var.control_plane_node_count + var.worker_node_count + (var.standalone_api_server ? 1 : 0) 10 | ocne_short_version = join("", [element(split("", var.ocne_version), 0), element(split("", var.ocne_version), 2)]) 11 | node_ocids = flatten(concat(module.control-plane-compute.node_ocids, module.worker-compute.node_ocids)) 12 | 13 | apiserver_init = templatefile("${path.module}/files/apiserver_init.sh", { 14 | os_version = var.os_version 15 | yum_repo_url = var.yum_repo_url 16 | ocne_short_version = local.ocne_short_version 17 | ocne_version = var.ocne_version 18 | compute_user = var.compute_user 19 | kernel_version = var.kernel_version 20 | } 21 | ) 22 | 23 | agent_init = templatefile("${path.module}/files/agent_init.sh", { 24 | os_version = var.os_version 25 | yum_repo_url = var.yum_repo_url 26 | } 27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | module "images" { 5 | source = "../oci-ocne-images" 6 | count = length(var.image_ocid) != 0 ? 0 : 1 7 | compartment_id = var.compartment_id 8 | os_version = var.os_version 9 | } 10 | 11 | module "kube-apiserver-loadbalancer" { 12 | source = "../oci-ocne-loadbalancer" 13 | compartment_id = var.compartment_id 14 | prefix = "${var.prefix}-cp" 15 | subnet_id = var.subnet_id 16 | shape = var.load_balancer_shape 17 | policy = var.load_balancer_policy 18 | protocol = "TCP" 19 | port = var.kube_apiserver_port 20 | backends = { for ip in local.control_plane_nodes : ip => var.kube_apiserver_port } 21 | backend_count = var.control_plane_node_count 22 | instance_count = var.virtual_ip ? 0 : 1 23 | 24 | # Optional 25 | freeform_tags = var.freeform_tags 26 | } 27 | 28 | module "api-server-compute" { 29 | source = "../oci-ocne-compute" 30 | depends_on = [module.images] 31 | 32 | availability_domain_id = var.availability_domain_id 33 | compartment_id = var.compartment_id 34 | prefix = "${var.prefix}-api-server" 35 | init_script = local.apiserver_init 36 | instance_count = 1 37 | image_ocid = length(var.image_ocid) != 0 ? var.image_ocid : module.images[0].image_ocid 38 | subnet_id = var.subnet_id 39 | instance_shape = var.instance_shape 40 | ssh_public_key_path = var.ssh_public_key_path 41 | ssh_private_key_path = var.ssh_private_key_path 42 | enable_bastion = var.enable_bastion 43 | bastion_public_ip = var.bastion_public_ip 44 | bastion_user = var.bastion_user 45 | bastion_private_key_path = var.bastion_private_key_path 46 | compute_user = var.compute_user 47 | freeform_tags = var.freeform_tags 48 | attach_secondary_vnic = var.standalone_api_server ? false : var.virtual_ip 49 | } 50 | 51 | module "control-plane-compute" { 52 | source = "../oci-ocne-compute" 53 | depends_on = [module.images] 54 | 55 | availability_domain_id = var.availability_domain_id 56 | compartment_id = var.compartment_id 57 | prefix = "${var.prefix}-control-plane" 58 | init_script = local.agent_init 59 | instance_count = var.standalone_api_server ? var.control_plane_node_count : var.control_plane_node_count - 1 60 | image_ocid = length(var.image_ocid) != 0 ? var.image_ocid : module.images[0].image_ocid 61 | subnet_id = var.subnet_id 62 | instance_shape = var.instance_shape 63 | ssh_public_key_path = var.ssh_public_key_path 64 | ssh_private_key_path = var.ssh_private_key_path 65 | enable_bastion = var.enable_bastion 66 | bastion_public_ip = var.bastion_public_ip 67 | bastion_user = var.bastion_user 68 | bastion_private_key_path = var.bastion_private_key_path 69 | compute_user = var.compute_user 70 | freeform_tags = var.freeform_tags 71 | attach_secondary_vnic = var.standalone_api_server ? var.virtual_ip : false 72 | } 73 | 74 | module "worker-compute" { 75 | source = "../oci-ocne-compute" 76 | depends_on = [module.images] 77 | 78 | availability_domain_id = var.availability_domain_id 79 | compartment_id = var.compartment_id 80 | prefix = "${var.prefix}-worker" 81 | init_script = local.agent_init 82 | instance_count = var.worker_node_count 83 | image_ocid = length(var.image_ocid) != 0 ? var.image_ocid : module.images[0].image_ocid 84 | subnet_id = var.subnet_id 85 | instance_shape = var.instance_shape 86 | ssh_public_key_path = var.ssh_public_key_path 87 | ssh_private_key_path = var.ssh_private_key_path 88 | enable_bastion = var.enable_bastion 89 | bastion_public_ip = var.bastion_public_ip 90 | bastion_user = var.bastion_user 91 | bastion_private_key_path = var.bastion_private_key_path 92 | compute_user = var.compute_user 93 | freeform_tags = var.freeform_tags 94 | } 95 | 96 | resource "null_resource" "copy_apiserver_ssh_key" { 97 | triggers = { 98 | control-plane-nodes = join(",", module.control-plane-compute.private_ip) 99 | worker-nodes = join(",", module.worker-compute.private_ip) 100 | } 101 | count = length(local.agents) 102 | depends_on = [module.api-server-compute, module.control-plane-compute, module.worker-compute] 103 | 104 | provisioner "local-exec" { 105 | command = < RPM" 140 | ] 141 | } 142 | 143 | provisioner "local-exec" { 144 | command = < /dev/null ; do :; done 151 | 152 | ssh -i ${var.ssh_private_key_path} -o StrictHostKeyChecking=no -o ProxyCommand="ssh -i ${var.bastion_private_key_path} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -W %h:%p ${var.bastion_user}@${var.bastion_public_ip}" ${var.compute_user}@${local.all_nodes[count.index]} \ 153 | 'sudo dnf remove -y $RPM && \ 154 | rm -f RPM' 155 | fi 156 | 157 | if [[ ${var.enable_bastion} == false && "${var.bastion_public_ip}" == "" ]] ; then 158 | ssh -i ${var.ssh_private_key_path} -o StrictHostKeyChecking=no ${var.compute_user}@${local.all_nodes[count.index]} \ 159 | 'rpm -qa | grep uek > RPM && \ 160 | sudo dnf install -y kernel-uek && \ 161 | (sleep 2 && \ 162 | sudo reboot)&' && \ 163 | until ssh -i ${var.ssh_private_key_path} -o StrictHostKeyChecking=no ${var.compute_user}@${local.all_nodes[count.index]} true 2> /dev/null ; do :; done 164 | fi 165 | EOF 166 | } 167 | 168 | provisioner "remote-exec" { 169 | inline = [ 170 | "sudo dnf remove -y $(cat RPM)", 171 | "rm -f RPM" 172 | ] 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "apiserver_ip" { 5 | description = "IP address of API Server." 6 | value = local.apiserver_ip 7 | } 8 | 9 | output "control_plane_nodes" { 10 | description = "List of control plane nodes." 11 | value = local.control_plane_nodes 12 | } 13 | 14 | output "worker_nodes" { 15 | description = "List of worker node IP addresses." 16 | value = module.worker-compute.private_ip 17 | } 18 | 19 | output "load_balancer_ocid" { 20 | description = "OCID of the load balancer." 21 | value = module.kube-apiserver-loadbalancer.load_balancer_ocid 22 | } 23 | 24 | output "load_balancer_ip" { 25 | description = "IP address of the load balancer." 26 | value = module.kube-apiserver-loadbalancer.ip_address 27 | } 28 | 29 | output "kubernetes_endpoint" { 30 | description = "Load balancer URI." 31 | value = module.kube-apiserver-loadbalancer.endpoint 32 | } 33 | 34 | output "node_ocids" { 35 | description = "List of worker node IP addresses." 36 | value = local.node_ocids 37 | } 38 | 39 | output "kube_apiserver_virtual_ip" { 40 | description = "The 2nd IP of first control plane node to be the Kubernetes API server endpoint" 41 | value = var.virtual_ip ? (var.standalone_api_server ? module.control-plane-compute.secondary_private_ip[0] : module.api-server-compute.secondary_private_ip[0]) : "" 42 | } 43 | 44 | output "image_ocid" { 45 | description = "The OCID of the OS image to use when creating all compute resources that are part of this deployment" 46 | value = length(var.image_ocid) != 0 ? var.image_ocid : module.images[0].image_ocid 47 | } -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // Common OCI resource variables 5 | variable "availability_domain_id" { 6 | type = string 7 | description = "The ID of the availability domain inside the `region` in which to create this deployment" 8 | } 9 | 10 | variable "compartment_id" { 11 | type = string 12 | description = "The OCID of the compartment in which to create this deployment" 13 | } 14 | 15 | variable "prefix" { 16 | type = string 17 | description = "A unique prefix to attach to the name of all cloud resources that are created as a part of this deployment" 18 | } 19 | 20 | variable "instance_shape" { 21 | type = map(any) 22 | description = "The OCI instance shape to use for all compute resources that are created as part of this deployment" 23 | } 24 | 25 | variable "image_ocid" { 26 | type = string 27 | description = "The OCID of the OS image to use when creating all compute resources that are part of this deployment" 28 | default = "" 29 | } 30 | 31 | variable "os_version" { 32 | type = string 33 | description = "The version of Oracle Linux to use as the base image for all compute resources that are part of this deployemnt" 34 | } 35 | 36 | variable "kernel_version" { 37 | type = string 38 | description = "Kernel version to be installed" 39 | } 40 | 41 | variable "subnet_id" { 42 | type = string 43 | description = "The OCID of a pre-existing subnet that all newly created cloud resources will be configured to use. If this variable to set to the empty string, a network configuration will be generated automatically" 44 | } 45 | 46 | // Compute instance specific variables 47 | variable "ssh_public_key_path" { 48 | type = string 49 | description = "The SSH public key path to use when configuring access to any compute resources created as part of this deployment" 50 | } 51 | 52 | variable "ssh_private_key_path" { 53 | type = string 54 | description = "THe SSH private key path that goes with the SSH public key that is used when accessing compute resources that are created as part of this deployment" 55 | } 56 | 57 | // Instance pool specific variables 58 | variable "load_balancer_shape" { 59 | type = map(string) 60 | description = "The OCI load balancer shape to use when creating load balancers for this deployment" 61 | } 62 | 63 | variable "load_balancer_policy" { 64 | type = string 65 | description = "The traffic policy to apply to any load balancers that are created as part of this deployment" 66 | default = "LEAST_CONNECTIONS" 67 | } 68 | 69 | variable "ocne_version" { 70 | type = string 71 | description = "The version and release of OCNE to deploy" 72 | } 73 | 74 | variable "yum_repo_url" { 75 | type = string 76 | description = "The URI of the yum repository that hosts all OCNE packages" 77 | } 78 | 79 | variable "control_plane_node_count" { 80 | type = number 81 | description = "The number of Kubernetes control plane nodes to deploy" 82 | } 83 | 84 | variable "worker_node_count" { 85 | type = number 86 | description = "The number of Kubernetes worker nodes to deploy" 87 | } 88 | 89 | variable "standalone_api_server" { 90 | type = bool 91 | description = "If true, a dedicated compute instance is allocated for the OCNE API Server. Otherwise, it will be deployed onto one of the Kubernetes control plane nodes" 92 | default = true 93 | } 94 | 95 | variable "use_vault" { 96 | type = bool 97 | description = "Decides if Vault is used to requisition certificates for OCNE daemons. If true, then certificates are allocated using a Vault instance. Otherwise, this module will generate certificates and distribute them to each node" 98 | default = false 99 | } 100 | 101 | variable "environment_name" { 102 | type = string 103 | description = "The name of the OCNE Environment that is created by this module to deploy module instances into" 104 | default = "myenvironment" 105 | } 106 | 107 | variable "kubernetes_name" { 108 | type = string 109 | description = "The name of the instance of the OCNE Kubernetes module that is installed as part of this deployment" 110 | default = "mycluster" 111 | } 112 | 113 | variable "kube_apiserver_port" { 114 | type = string 115 | description = "The port to use for the Kubernetes API server that is created as part of this deployment" 116 | default = "6443" 117 | } 118 | 119 | variable "container_registry" { 120 | type = string 121 | description = "The container image registry that contains all container images that are consumed by this deployment" 122 | default = "container-registry.oracle.com/olcne" 123 | } 124 | 125 | variable "compute_user" { 126 | type = string 127 | description = "A user configured with sudo access and authenticated with ssh_public_key_path and ssh_private_key_path on each compute resource" 128 | } 129 | 130 | // OCNE variables 131 | variable "enable_bastion" { 132 | type = bool 133 | description = "Decides if bastion is installed. Intended for internal use. Set to false." 134 | } 135 | 136 | variable "bastion_public_ip" { 137 | type = string 138 | description = "Public IP address of the Bastion host" 139 | } 140 | 141 | variable "bastion_user" { 142 | type = string 143 | description = "User name on the Bastion host" 144 | default = "opc" 145 | } 146 | 147 | variable "bastion_private_key_path" { 148 | type = string 149 | description = "The location of the SSH private key for the Bastion host" 150 | } 151 | 152 | variable "freeform_tags" { 153 | description = "Freeform tags with useful miscellaneous information." 154 | type = map(any) 155 | default = {} 156 | } 157 | 158 | variable "virtual_ip" { 159 | type = bool 160 | description = "Setup Kubernetes API server endpoint on a virtual IP address representing all the Kubernetes control plane nodes" 161 | default = false 162 | } 163 | -------------------------------------------------------------------------------- /modules/terraform-oci-ocne-infrastructure/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Terraform template 3 | # Local .terraform directories 4 | **/.terraform/* 5 | 6 | # .tfstate files 7 | *.tfstate 8 | *.tfstate.* 9 | 10 | # Crash log files 11 | crash.log 12 | 13 | # Ignore any .tfvars files that are generated automatically for each Terraform run. Most 14 | # .tfvars files are managed as part of configuration and so should be included in 15 | # version control. 16 | # 17 | # example.tfvars 18 | 19 | # Ignore override files as they are usually used to override resources locally and so 20 | # are not checked in 21 | override.tf 22 | override.tf.json 23 | *_override.tf 24 | *_override.tf.json 25 | 26 | # Include override files you do wish to add to version control using negated pattern 27 | # 28 | # !example_override.tf 29 | 30 | # Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan 31 | # example: *tfplan* 32 | 33 | ### JetBrains template 34 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 35 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 36 | 37 | # User-specific stuff 38 | .idea/**/workspace.xml 39 | .idea/**/tasks.xml 40 | .idea/**/usage.statistics.xml 41 | .idea/**/dictionaries 42 | .idea/**/shelf 43 | 44 | # Generated files 45 | .idea/**/contentModel.xml 46 | 47 | # Sensitive or high-churn files 48 | .idea/**/dataSources/ 49 | .idea/**/dataSources.ids 50 | .idea/**/dataSources.local.xml 51 | .idea/**/sqlDataSources.xml 52 | .idea/**/dynamic.xml 53 | .idea/**/uiDesigner.xml 54 | .idea/**/dbnavigator.xml 55 | 56 | # Gradle 57 | .idea/**/gradle.xml 58 | .idea/**/libraries 59 | 60 | # Gradle and Maven with auto-import 61 | # When using Gradle or Maven with auto-import, you should exclude module files, 62 | # since they will be recreated, and may cause churn. Uncomment if using 63 | # auto-import. 64 | # .idea/modules.xml 65 | # .idea/*.iml 66 | # .idea/modules 67 | # *.iml 68 | # *.ipr 69 | 70 | # CMake 71 | cmake-build-*/ 72 | 73 | # Mongo Explorer plugin 74 | .idea/**/mongoSettings.xml 75 | 76 | # File-based project format 77 | *.iws 78 | 79 | # IntelliJ 80 | out/ 81 | 82 | # mpeltonen/sbt-idea plugin 83 | .idea_modules/ 84 | 85 | # JIRA plugin 86 | atlassian-ide-plugin.xml 87 | 88 | # Cursive Clojure plugin 89 | .idea/replstate.xml 90 | 91 | # Crashlytics plugin (for Android Studio and IntelliJ) 92 | com_crashlytics_export_strings.xml 93 | crashlytics.properties 94 | crashlytics-build.properties 95 | fabric.properties 96 | 97 | # Editor-based Rest Client 98 | .idea/httpRequests 99 | 100 | # Android studio 3.1+ serialized cache file 101 | .idea/caches/build_file_checksums.ser 102 | 103 | 104 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/README.md: -------------------------------------------------------------------------------- 1 | # terraform-oci-vault 2 | 3 | This module deploys Hashicorp Vault in an autoscaling configuration complete with cloud-backed secret storage, a load balancer, and auto-unsealing. 4 | 5 | 6 | ## Getting Started 7 | 8 | The best place to start when using these Terraform modules is in the `terraform-oci-olcne` module. This module deploys a complete OCNE stack including a Kubernetes cluster. 9 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/datasources.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | data "template_file" "vault_config_template" { 5 | template = file("${path.module}/templates/vault.template") 6 | 7 | vars = { 8 | obj_namespace = var.vault_namespace 9 | obj_bucket = oci_objectstorage_bucket.vault_storage_backend_bucket.name 10 | obj_lock_bucket = oci_objectstorage_bucket.vault_storage_backend_ha_bucket.name 11 | kms_key_id = module.vault-kms.key_id 12 | kms_crypto_endpoint = module.vault-kms.crypto_endpoint 13 | kms_management_endpoint = module.vault-kms.management_endpoint 14 | } 15 | } 16 | 17 | data "template_file" "vault_setup" { 18 | template = file("${path.module}/templates/vault_setup") 19 | 20 | vars = { 21 | VIF = "/tmp/vault.init" 22 | VIF_base64 = "/tmp/vault_init_base64.json" 23 | VAULT_ADDR = "https://127.0.0.1:8200" 24 | VAULT_SKIP_VERIFY = "true" 25 | user_id = var.user_id 26 | region = var.region 27 | compartment_id = var.compartment_id 28 | vault_ocid = var.vault_ocid 29 | key_ocid = var.key_ocid 30 | secret_name = var.secret_name 31 | ocne_secret_name = var.ocne_secret_name 32 | secretfile = "" 33 | RT = "" 34 | CT = "/tmp/client.token" 35 | CT_base64 = "/tmp/client_token_base64.json" 36 | api_key_file = "/etc/vault.d/.oci/oci_api_key.pem" 37 | compute_user = var.compute_user 38 | } 39 | } 40 | 41 | data "template_file" "cloudinit_template" { 42 | template = file("${path.module}/templates/cloudinit.template") 43 | 44 | vars = { 45 | vault_version = var.vault_version 46 | config = base64gzip(data.template_file.vault_config_template.rendered) 47 | proxy = var.proxy 48 | tenancy_id = var.tenancy_id 49 | user_id = var.user_id 50 | region = var.region 51 | fingerprint = var.fingerprint 52 | password = var.private_key_password 53 | key_file = base64gzip(file(var.api_private_key_path)) 54 | vault_setup = base64gzip(data.template_file.vault_setup.rendered) 55 | lb_ip = module.vault-autoscaler.load_balancer_ip 56 | ocne-cert-engine-policy = base64gzip(file("${path.module}/templates/ocne-cert-engine-policy.hcl")) 57 | } 58 | } 59 | 60 | data "template_cloudinit_config" "vault" { 61 | gzip = true 62 | base64_encode = true 63 | 64 | part { 65 | filename = "vault.yaml" 66 | content_type = "text/cloud-config" 67 | content = data.template_file.cloudinit_template.rendered 68 | } 69 | } 70 | 71 | data "external" "fetch_token" { 72 | depends_on = [null_resource.vault_setup] 73 | program = ["sh", "${path.module}/templates/fetch_token"] 74 | query = { 75 | compute_user = var.compute_user 76 | vault_host = module.vault-autoscaler.instances[0] 77 | compartment_id = var.compartment_id 78 | ocne_secret_name = var.ocne_secret_name 79 | ssh_private_key_path = var.ssh_private_key_path 80 | region = var.region 81 | bastion_user = var.bastion_user 82 | bastion_public_ip = var.bastion_public_ip 83 | bastion_private_key_path = var.bastion_private_key_path 84 | enable_bastion = var.enable_bastion 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/main.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | resource "null_resource" "delete_vault_storage_backend_bucket" { 5 | triggers = { 6 | vault_primary_node = element(module.vault-autoscaler.instances, 0) 7 | bastion_public_ip = var.bastion_public_ip 8 | bastion_user = var.bastion_user 9 | bastion_private_key = var.enable_bastion || var.bastion_public_ip != "" ? file(var.bastion_private_key_path) : "" 10 | compute_user = var.compute_user 11 | ssh_private_key_path = var.ssh_private_key_path 12 | prefix = var.prefix 13 | } 14 | provisioner "remote-exec" { 15 | when = destroy 16 | connection { 17 | agent = false 18 | timeout = "10m" 19 | host = self.triggers.vault_primary_node 20 | user = self.triggers.compute_user 21 | private_key = file(self.triggers.ssh_private_key_path) 22 | bastion_host = self.triggers.bastion_public_ip 23 | bastion_user = self.triggers.bastion_user 24 | bastion_private_key = self.triggers.bastion_private_key 25 | } 26 | inline = [ 27 | "set -x", 28 | "export OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True && oci os object bulk-delete -bn ${self.triggers.prefix}-bucket --force", 29 | "export OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True && oci os object bulk-delete -bn ${self.triggers.prefix}-ha-bucket --force" 30 | ] 31 | } 32 | } 33 | 34 | resource "oci_objectstorage_bucket" "vault_storage_backend_bucket" { 35 | compartment_id = var.compartment_id 36 | name = "${var.prefix}-bucket" 37 | namespace = var.vault_namespace 38 | 39 | # Optional 40 | freeform_tags = var.freeform_tags 41 | } 42 | 43 | resource "oci_objectstorage_bucket" "vault_storage_backend_ha_bucket" { 44 | compartment_id = var.compartment_id 45 | name = "${var.prefix}-ha-bucket" 46 | namespace = var.vault_namespace 47 | 48 | # Optional 49 | freeform_tags = var.freeform_tags 50 | } 51 | 52 | module "images" { 53 | source = "../oci-ocne-images" 54 | 55 | compartment_id = var.compartment_id 56 | os_version = "8" 57 | } 58 | 59 | module "vault-autoscaler" { 60 | source = "../oci-ocne-autoscaling" 61 | 62 | availability_domain_id = var.availability_domain_id 63 | compartment_id = var.compartment_id 64 | prefix = var.prefix 65 | instance_shape = var.instance_shape 66 | image_ocid = module.images.image_ocid 67 | subnet_id = var.subnet_id 68 | ssh_public_key_path = var.ssh_public_key_path 69 | pool_size = var.pool_size 70 | load_balancer_protocol = var.load_balancer_protocol 71 | load_balancer_port = var.load_balancer_port 72 | load_balancer_ocid = var.load_balancer_ocid 73 | load_balancer_ip = var.load_balancer_ip 74 | load_balancer_shape = var.load_balancer_shape 75 | create_load_balancer = var.create_load_balancer 76 | 77 | instance_user_data = data.template_cloudinit_config.vault.rendered 78 | freeform_tags = var.freeform_tags 79 | } 80 | 81 | module "vault-kms" { 82 | source = "../oci-ocne-kms" 83 | 84 | compartment_id = var.compartment_id 85 | prefix = var.prefix 86 | vault_ocid = var.vault_ocid 87 | key_ocid = var.key_ocid 88 | freeform_tags = var.freeform_tags 89 | } 90 | 91 | resource "null_resource" "vault_setup" { 92 | depends_on = [module.vault-autoscaler] 93 | 94 | provisioner "remote-exec" { 95 | connection { 96 | agent = false 97 | timeout = "10m" 98 | host = element(module.vault-autoscaler.instances, 0) 99 | user = var.compute_user 100 | private_key = file(var.ssh_private_key_path) 101 | bastion_host = var.bastion_public_ip 102 | bastion_user = var.bastion_user 103 | bastion_private_key = var.enable_bastion || var.bastion_public_ip != "" ? file(var.bastion_private_key_path) : "" 104 | } 105 | inline = [ 106 | "set -x", 107 | "sudo /usr/bin/cloud-init status --wait 1> /dev/null", 108 | "timeout 300 bash -c 'while [[ \"$(curl -skL -o /dev/null -w ''%%{http_code}'' https://${module.vault-autoscaler.load_balancer_ip}:${var.load_balancer_port})\" != \"200\" ]]; do sleep 1; done' || false" 109 | ] 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/output.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | output "vault_ocne_client_token" { 5 | description = "OCNE certificate signing token." 6 | value = data.external.fetch_token.result["vault_ocne_client_token"] 7 | } 8 | 9 | output "uri" { 10 | depends_on = [null_resource.vault_setup] 11 | description = "Load balancer URI." 12 | value = "https://${module.vault-autoscaler.load_balancer_ip}:${var.load_balancer_port}" 13 | } 14 | 15 | output "instances" { 16 | description = "List of vault instances." 17 | value = module.vault-autoscaler.instances 18 | } 19 | 20 | output "vault_storage_bucket" { 21 | description = "vault storage backend bucket" 22 | value = oci_objectstorage_bucket.vault_storage_backend_bucket.name 23 | } 24 | 25 | output "vault_ha_storage_bucket" { 26 | description = "vault storage HA backend bucket" 27 | value = oci_objectstorage_bucket.vault_storage_backend_ha_bucket.name 28 | } 29 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/templates/cloudinit.template: -------------------------------------------------------------------------------- 1 | #cloud-config 2 | write_files: 3 | - content: | 4 | [Unit] 5 | Description="HashiCorp Vault - A tool for managing secrets" 6 | Documentation=https://www.vaultproject.io/docs/ 7 | Requires=network-online.target 8 | After=network-online.target 9 | ConditionFileNotEmpty=/etc/vault.d/vault.hcl 10 | 11 | [Service] 12 | User=vault 13 | Group=vault 14 | ProtectSystem=full 15 | ProtectHome=read-only 16 | PrivateTmp=yes 17 | PrivateDevices=yes 18 | SecureBits=keep-caps 19 | AmbientCapabilities=CAP_IPC_LOCK 20 | Capabilities=CAP_IPC_LOCK+ep 21 | CapabilityBoundingSet=CAP_SYSLOG CAP_IPC_LOCK 22 | NoNewPrivileges=yes 23 | ExecStart=/usr/bin/vault_env /usr/bin/vault server -config=/etc/vault.d/vault.hcl 24 | ExecReload=/bin/kill --signal HUP $MAINPID 25 | ExecStartPost=/usr/bin/timeout 30 sh -c 'while ! ss -H -t -l -n sport = :8200 | grep -q "^LISTEN.*:8200"; do sleep 1; done' 26 | KillMode=process 27 | KillSignal=SIGINT 28 | Restart=on-failure 29 | RestartSec=5 30 | TimeoutStopSec=30 31 | StartLimitBurst=3 32 | LimitNOFILE=65536 33 | 34 | [Install] 35 | WantedBy=multi-user.target 36 | path: /usr/lib/systemd/system/vault.service 37 | - content: | 38 | [Unit] 39 | Requires=vault.service 40 | After=vault.service 41 | 42 | [Service] 43 | Type=oneshot 44 | ExecStart=/usr/bin/vault_setup 45 | RemainAfterExit=true 46 | 47 | [Install] 48 | WantedBy=multi-user.target 49 | path: /usr/lib/systemd/system/vault-init.service 50 | - content: | 51 | #! /usr/bin/bash 52 | export VAULT_API_ADDR=$(hostname):8200 53 | "$@" 54 | path: /usr/bin/vault_env 55 | permissions: 0755 56 | - encoding: "gzip+base64" 57 | content: ${ocne-cert-engine-policy} 58 | path: /etc/vault.d/ocne-cert-engine-policy.hcl 59 | - encoding: "gzip+base64" 60 | content: ${vault_setup} 61 | path: /usr/bin/vault_setup 62 | permissions: 0755 63 | - encoding: "gzip+base64" 64 | content: ${key_file} 65 | path: /root/.oci/oci_api_key.pem 66 | - content: | 67 | [DEFAULT] 68 | user=${user_id} 69 | fingerprint=${fingerprint} 70 | key_file=/etc/vault.d/.oci/oci_api_key.pem 71 | tenancy=${tenancy_id} 72 | region=${region} 73 | pass_phrase=${password} 74 | path: /etc/vault.d/.oci/config 75 | - encoding: "gzip+base64" 76 | path: /etc/vault.d/.oci/oci_api_key.pem 77 | content: ${key_file} 78 | - encoding: "gzip+base64" 79 | content: ${config} 80 | path: /etc/vault.d/vault.hcl 81 | - content: | 82 | [req] 83 | default_bits=2048 84 | encrypt_key=no 85 | default_md=sha256 86 | prompt=no 87 | utf8=yes 88 | distinguished_name=req_distinguished_name 89 | req_extensions=v3_req 90 | [req_distinguished_name] 91 | C=US 92 | ST=California 93 | L="Redwood City" 94 | O="Oracle America" 95 | OU="Private Cloud" 96 | CN=HN 97 | [v3_req] 98 | subjectKeyIdentifier=hash 99 | keyUsage=digitalSignature, keyEncipherment 100 | extendedKeyUsage=clientAuth, serverAuth 101 | subjectAltName=@alt_names 102 | [ alt_names ] 103 | DNS.1=localhost 104 | IP.1=127.0.0.1 105 | IP.2=PIP 106 | IP.3=LBIP 107 | path: /etc/vault.d/cert.csr 108 | permissions: 0666 109 | - content: | 110 | export VAULT_SKIP_VERIFY=true 111 | export VAULT_FORMAT=json 112 | path: /etc/profile.d/vault.sh 113 | runcmd: 114 | - sed -i "s/HN/$(hostname)/" /etc/vault.d/cert.csr 115 | - sed -i "s/LBIP/${lb_ip}/" /etc/vault.d/cert.csr 116 | - sed -i "s/PIP/$(curl -Ls http://169.254.169.254/opc/v1/vnics | jq '.[0].privateIp')/" /etc/vault.d/cert.csr 117 | - openssl req -new -newkey rsa:2048 -days 3650 -nodes -x509 -subj "/C=US/ST=California/L=Redwood City/O=Oracle America CA" -keyout /etc/vault.d/cert.key -out /etc/vault.d/cert.pem -extensions v3_req -config /etc/vault.d/cert.csr 118 | - [sh, -c, "HTTPS_PROXY=${proxy} curl --silent --remote-name https://releases.hashicorp.com/vault/${vault_version}/vault_${vault_version}_linux_amd64.zip"] 119 | - unzip vault_${vault_version}_linux_amd64.zip 120 | - cp vault /usr/bin/vault 121 | - sudo setcap cap_ipc_lock=+ep /usr/bin/vault 122 | - sudo useradd --system --home /etc/vault.d --shell /bin/false vault 123 | - sudo chown --recursive vault:vault /etc/vault.d 124 | - systemctl daemon-reload 125 | - systemctl enable vault.service 126 | - systemctl start vault.service 127 | - systemctl start vault-init.service 128 | - while [ ! -f /tmp/vault_setup_finish ] ; do sleep 15 ; done 129 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/templates/fetch_token: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 4 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 5 | 6 | parse_input() { 7 | eval "$(jq -r '"compute_user=\(.compute_user) 8 | vault_host=\(.vault_host) 9 | compartment_id=\(.compartment_id) 10 | ocne_secret_name=\(.ocne_secret_name) 11 | ssh_private_key_path=\(.ssh_private_key_path) 12 | region=\(.region) 13 | bastion_user=\(.bastion_user) 14 | bastion_public_ip=\(.bastion_public_ip) 15 | bastion_private_key_path=\(.bastion_private_key_path) 16 | enable_bastion=\(.enable_bastion)"')" 17 | } 18 | 19 | fetch_token() { 20 | if [[ ${enable_bastion} == true || "${bastion_public_ip}" != "" ]] ; then 21 | vault_ocne_client_token=$(ssh -i ${ssh_private_key_path} -o StrictHostKeyChecking=no -o ProxyCommand="ssh -i ${bastion_private_key_path} -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no $bastion_user@${bastion_public_ip} nc $vault_host 22" $compute_user@$vault_host 'export OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True && oci vault secret list --compartment-id '$compartment_id' --name '$ocne_secret_name' | jq -r '"'"'.data[].id'"'"' | xargs -I{} oci secrets secret-bundle get --secret-id {} --stage CURRENT --region '$region' | jq -r '"'"'.data."secret-bundle-content".content'"'"' | base64 -d' | tr -d '') 22 | elif [[ ${enable_bastion} == false && "${bastion_public_ip}" == "" ]] ; then 23 | vault_ocne_client_token=$(ssh -i ${ssh_private_key_path} -o StrictHostKeyChecking=no $compute_user@$vault_host 'export OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True && oci vault secret list --compartment-id '$compartment_id' --name '$ocne_secret_name' | jq -r '"'"'.data[].id'"'"' | xargs -I{} oci secrets secret-bundle get --secret-id {} --stage CURRENT --region '$region' | jq -r '"'"'.data."secret-bundle-content".content'"'"' | base64 -d' | tr -d '') 24 | fi 25 | 26 | if [ -z "$vault_ocne_client_token" ] ; then 27 | echo "FATAL: problem in fetching ocne vault client token. vault_ocne_client_token=${vault_ocne_client_token}" 28 | exit 1 29 | fi 30 | jq -n --arg vault_ocne_client_token "$vault_ocne_client_token" '{"vault_ocne_client_token":$vault_ocne_client_token}' 31 | } 32 | 33 | parse_input 34 | fetch_token 35 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/templates/ocne-cert-engine-policy.hcl: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | # Work with pki secrets engine 5 | path "pki*" { 6 | capabilities = [ "create", "read", "update", "delete", "list", "sudo" ] 7 | } 8 | 9 | # OCNE specific capabilities 10 | path "+/ocne*" { 11 | capabilities = [ "create", "read", "update", "delete", "list", "sudo" ] 12 | } 13 | 14 | path "+/+/ocne*" { 15 | capabilities = [ "create", "read", "update", "delete", "list", "sudo" ] 16 | } 17 | 18 | path "+/+/+/ocne*" { 19 | capabilities = [ "create", "read", "update", "delete", "list", "sudo" ] 20 | } 21 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/templates/vault.template: -------------------------------------------------------------------------------- 1 | ui = true 2 | storage "oci" { 3 | namespace_name = "${obj_namespace}" 4 | bucket_name = "${obj_bucket}" 5 | ha_enabled = "true" 6 | lock_bucket_name = "${obj_lock_bucket}" 7 | auth_type_api_key = "true" 8 | } 9 | seal "ocikms" { 10 | key_id = "${kms_key_id}" 11 | crypto_endpoint = "${kms_crypto_endpoint}" 12 | management_endpoint = "${kms_management_endpoint}" 13 | auth_type_api_key = "true" 14 | } 15 | listener "tcp" { 16 | address = "[::]:8200" 17 | cluster_address = "[::]:8201" 18 | tls_cipher_suites = "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA" 19 | tls_disable = false 20 | tls_prefer_server_cipher_suites = true 21 | tls_cert_file = "/etc/vault.d/cert.pem" 22 | tls_key_file = "/etc/vault.d/cert.key" 23 | } 24 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/templates/vault_env: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | #! /usr/bin/bash 5 | 6 | export VAULT_API_ADDR=$(hostname):8200 7 | 8 | "$@" 9 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/templates/vault_setup: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | #! /usr/bin/bash 5 | 6 | firewall-cmd --add-port=8200/tcp 7 | firewall-cmd --add-port=8200/tcp --permanent 8 | firewall-cmd --add-port=8201/tcp 9 | firewall-cmd --add-port=8201/tcp --permanent 10 | 11 | export VIF=${VIF} 12 | export VIF_base64=${VIF_base64} 13 | export VAULT_ADDR=${VAULT_ADDR} 14 | export VAULT_SKIP_VERIFY=${VAULT_SKIP_VERIFY} 15 | export VAULT_FORMAT=json 16 | export OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True 17 | export CT=${CT} 18 | export CT_base64=${CT_base64} 19 | 20 | 21 | vault operator init -status 22 | if [ $? -ne 2 ]; then 23 | exit 0 24 | fi 25 | 26 | 27 | ## OCI Client configuration 28 | dnf config-manager --set-enabled ol8_developer 29 | yum install -y python36-oci-cli 30 | cp /etc/vault.d/.oci/config ~/.oci/ 31 | oci iam user api-key upload --user-id ${user_id} --key-file ${api_key_file} 32 | mkdir /home/${compute_user}/.oci/ 33 | cp /etc/vault.d/.oci/config /home/${compute_user}/.oci/ 34 | chown -R ${compute_user}: /home/${compute_user}/.oci 35 | 36 | 37 | ## Vault configuration 38 | vault operator init -format=json > ${VIF} 39 | base64 ${VIF} > ${VIF_base64} 40 | secretfile="$(< ${VIF_base64})" 41 | 42 | if [[ ! `oci vault secret list --compartment-id ${compartment_id} | grep -w ${secret_name}` ]] 43 | then 44 | oci vault secret create-base64 --compartment-id ${compartment_id} --secret-name ${secret_name} --vault-id ${vault_ocid} --key-id ${key_ocid} --secret-content-content "$secretfile" --secret-content-name "vault_recovery_keys" --region ${region} 45 | else 46 | secret_id=$(oci vault secret list --compartment-id ${compartment_id} --name ${secret_name} | grep vaultsecret | awk -F '"' '{print $4}') 47 | oci vault secret update-base64 --secret-id $secret_id --secret-content-content "$secretfile" 48 | fi 49 | 50 | RT=$(oci vault secret list --compartment-id ${compartment_id} --name ${secret_name} | jq -r '.data[].id' | xargs -I{} oci secrets secret-bundle get --secret-id {} --stage CURRENT --region ${region} | jq -r '.data."secret-bundle-content".content' | base64 -d | jq -r '.root_token') 51 | 52 | 53 | for i in {1..10}; do 54 | S=$(vault status) 55 | if [ $? -eq 0 ]; then 56 | echo "$S" | grep -q 'HA Mode.*active' 57 | if [ $? -eq 0 ]; then 58 | break 59 | fi 60 | fi 61 | sleep 5 62 | done 63 | 64 | vault login "$RT" 65 | vault secrets enable pki 66 | vault secrets tune -max-lease-ttl=87600h pki 67 | vault write -field=certificate pki/root/generate/internal common_name="ocne" ttl=87600h 68 | vault write pki/config/urls issuing_certificates="${VAULT_ADDR}/v1/pki/ca" crl_distribution_points="${VAULT_ADDR}/v1/pki/crl" 69 | vault secrets enable -path=ocne_pki_intermediary pki 70 | vault secrets tune -max-lease-ttl=87600h ocne_pki_intermediary 71 | vault write -format=json ocne_pki_intermediary/intermediate/generate/internal common_name="ocne Intermediate Authority" ttl="87600h" | jq -r '.data.csr' > pki_intermediate.csr 72 | vault write -format=json pki/root/sign-intermediate csr=@pki_intermediate.csr format=pem_bundle ttl="87600h" | jq -r '.data.certificate' > intermediate.cert.pem 73 | vault write ocne_pki_intermediary/intermediate/set-signed certificate=@intermediate.cert.pem 74 | vault write ocne_pki_intermediary/roles/ocne allow_any_name=true use_csr_common_name=false require_cn=false use_csr_san=false max_ttl="87600h" 75 | 76 | 77 | ## Create vault token based on the OCNE cert policy. 78 | vault policy write ocne-cert-engine-policy /etc/vault.d/ocne-cert-engine-policy.hcl 79 | vault token create -policy=ocne-cert-engine-policy | grep -w client_token | awk -F '"' '{print $4}' > ${CT} 80 | 81 | base64 ${CT} > ${CT_base64} 82 | secretfile="$(< ${CT_base64})" 83 | 84 | if [[ ! `oci vault secret list --compartment-id ${compartment_id} | grep -w ${ocne_secret_name}` ]] 85 | then 86 | oci vault secret create-base64 --compartment-id ${compartment_id} --secret-name ${ocne_secret_name} --vault-id ${vault_ocid} --key-id ${key_ocid} --secret-content-content "$secretfile" --secret-content-name "vault_recovery_keys" --region ${region} 87 | else 88 | secret_id=$(oci vault secret list --compartment-id ${compartment_id} --name ${ocne_secret_name} | grep vaultsecret | awk -F '"' '{print $4}') 89 | oci vault secret update-base64 --secret-id $secret_id --secret-content-content "$secretfile" 90 | fi 91 | 92 | 93 | # Remove files, which could lead to security breaches. 94 | rm -f pki_intermediate.csr intermediate.cert.pem ${VIF} ${VIF_base64} ${CT} ${CT_base64} 95 | 96 | 97 | # Touch finish file that can be checked by cloud-init. 98 | touch /tmp/vault_setup_finish 99 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/variables.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // OCI Identity Variables 5 | variable "user_id" { 6 | type = string 7 | description = "The OCID of the user that will be used by Vault to access OCI resources" 8 | } 9 | 10 | variable "region" { 11 | type = string 12 | description = "The ID of the OCI Region where Vault is deployed" 13 | } 14 | 15 | variable "tenancy_id" { 16 | type = string 17 | description = "The OCID of the OCI Tenancy where Vault is deployed" 18 | } 19 | 20 | variable "fingerprint" { 21 | type = string 22 | description = "The fingerprint associated with the private key used by the OCI user to authentication" 23 | } 24 | 25 | variable "api_private_key_path" { 26 | type = string 27 | description = "The path to the private key used by the OCI user to authenticate" 28 | } 29 | 30 | variable "private_key_password" { 31 | type = string 32 | description = "The password used to decrypt the OCI user's private key" 33 | } 34 | 35 | // Common OCI resource variables 36 | variable "availability_domain_id" { 37 | type = string 38 | description = "The ID of the availability domain inside the `region` in which to create this deployment" 39 | } 40 | 41 | variable "compartment_id" { 42 | type = string 43 | description = "The OCID of the compartment in which to create this deployment" 44 | } 45 | 46 | variable "prefix" { 47 | type = string 48 | description = "A unique prefix to attach to the name of all cloud resources that are created as a part of this deployment" 49 | } 50 | 51 | variable "instance_shape" { 52 | type = map(any) 53 | description = "The OCI instance shape to use for all compute resources that are created as part of this deployment" 54 | } 55 | 56 | variable "subnet_id" { 57 | type = string 58 | description = "The OCID of a pre-existing subnet that all newly created cloud resources will be configured to use. If this variable to set to the empty string, a network configuration will be generated automatically" 59 | } 60 | 61 | variable "compute_user" { 62 | type = string 63 | description = "A user configured with sudo access and authenticated with ssh_public_key and ssh_private_key on each compute resource" 64 | } 65 | 66 | // Compute instance specific variables 67 | variable "ssh_public_key_path" { 68 | type = string 69 | description = "The SSH public key path to use when configuring access to any compute resources created as part of this deployment" 70 | } 71 | 72 | variable "ssh_private_key_path" { 73 | type = string 74 | description = "THe SSH private key path that goes with the SSH public key that is used when accessing compute resources that are created as part of this deployment" 75 | } 76 | 77 | // Instance pool specific variables 78 | variable "pool_size" { 79 | type = number 80 | description = "The initial number of Vault instances to spawn as part of this deployment" 81 | default = "1" 82 | } 83 | 84 | 85 | variable "load_balancer_protocol" { 86 | type = string 87 | description = "The protocol to select when creating the listener for the load balancer that talks to the Vault instances" 88 | default = "TCP" 89 | } 90 | 91 | variable "load_balancer_ocid" { 92 | type = string 93 | description = "The OCID of the load balancer to use. If one is not specified, a load balancer will be created" 94 | default = "" 95 | } 96 | 97 | variable "create_load_balancer" { 98 | type = string 99 | description = "Set to true if a load balancer should be created by this module to service Vault instances. Set to false to use an existing one" 100 | default = true 101 | } 102 | 103 | variable "load_balancer_ip" { 104 | type = string 105 | description = "If a custom load balancer is provided, set this to the canonical IP address of that load balancer" 106 | default = "" 107 | } 108 | 109 | variable "load_balancer_port" { 110 | type = string 111 | description = "The port that the generated load balancer listener is listening on" 112 | default = "8200" 113 | } 114 | 115 | variable "vault_namespace" { 116 | type = string 117 | description = "OCI Object storage bucket namespace string used to create the OCI Object Storage Bucket to support the [HashiCorp Vault OCI Object Storage Backend](https://www.vaultproject.io/docs/configuration/storage/oci-object-storage). To get the namespace string see [Understanding Object Storage Namespaces](https://docs.oracle.com/en-us/iaas/Content/Object/Tasks/understandingnamespaces.htm]" 118 | } 119 | 120 | variable "load_balancer_shape" { 121 | type = map(string) 122 | description = "The OCI shape of the load balancer to create to service this pool" 123 | } 124 | 125 | variable "vault_version" { 126 | type = string 127 | description = "The version of Vault that is installed" 128 | default = "1.3.4" 129 | } 130 | 131 | variable "proxy" { 132 | type = string 133 | description = "The https proxy that is used to download Vault. Set to the empty string if no proxy is required" 134 | } 135 | 136 | variable "vault_ocid" { 137 | type = string 138 | description = "The OCID of the OCI KMS Vault that stores the OCI KSM Vault Key that secures the auto-unseal data for Hashicorp Vault. If unset, an OCI KMS Vault will be created" 139 | } 140 | 141 | variable "key_ocid" { 142 | type = string 143 | description = "The OCID of an OCI KMS Vault Key that is within the OCI KMS Vault configured via `vault_ocid`. If not is not provided, an OCI KMS Vault key will be created" 144 | } 145 | 146 | variable "secret_name" { 147 | type = string 148 | description = "The name of the vault secret" 149 | } 150 | 151 | variable "ocne_secret_name" { 152 | type = string 153 | description = "The name of the ocne vault secret" 154 | } 155 | 156 | variable "enable_bastion" { 157 | type = bool 158 | description = "Decides if bastion is installed. Intended for internal use. Set to false." 159 | } 160 | 161 | variable "bastion_public_ip" { 162 | type = string 163 | description = "Public IP address of an existing Bastion host. This is set when we are not creating a bastion but need to use an existing one." 164 | } 165 | 166 | variable "bastion_user" { 167 | type = string 168 | description = "User name on the Bastion host" 169 | default = "opc" 170 | } 171 | 172 | variable "bastion_private_key_path" { 173 | type = string 174 | description = "The SSH private key path that goes with the SSH public key that is used when accessing the bastion host. Must be set to true if enable_bastion is set to true." 175 | } 176 | 177 | variable "freeform_tags" { 178 | description = "Freeform tags with useful miscellaneous information." 179 | type = map(any) 180 | default = {} 181 | } 182 | -------------------------------------------------------------------------------- /modules/terraform-oci-vault/versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | -------------------------------------------------------------------------------- /provider.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | provider "oci" { 5 | disable_auto_retries = false 6 | fingerprint = var.fingerprint 7 | private_key_path = var.api_private_key_path 8 | region = var.region 9 | retry_duration_seconds = 60 10 | tenancy_ocid = var.tenancy_id 11 | user_ocid = var.user_id 12 | } 13 | -------------------------------------------------------------------------------- /state_backend.tf.example: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | backend "s3" { 6 | bucket = "" 7 | key = "/terraform.tfstate" 8 | region = "" 9 | endpoint = "" 10 | shared_credentials_file = "" 11 | skip_region_validation = true 12 | skip_credentials_validation = true 13 | skip_metadata_api_check = true 14 | force_path_style = true 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /terraform.tfvars.example: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | // OCI Identity Variables 5 | tenancy_id = "" 6 | compartment_id = "" 7 | user_id = "" 8 | fingerprint = "" 9 | api_private_key_path = "" 10 | 11 | // Common OCI resource variables 12 | region = "" 13 | availability_domain_id = "" 14 | prefix = "" 15 | 16 | // Compute instance specific variables 17 | ssh_public_key_path = "" 18 | ssh_private_key_path = "" 19 | 20 | // Bastion specific variables 21 | bastion_private_key_path = "" 22 | 23 | // OCNE Overrides 24 | control_plane_node_count = "3" 25 | worker_node_count = "3" 26 | environment_name = "myenvironment" 27 | kubernetes_name = "mycluster" 28 | 29 | -------------------------------------------------------------------------------- /versions.tf: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Oracle Corporation and/or affiliates. All rights reserved. 2 | # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl 3 | 4 | terraform { 5 | required_providers { 6 | oci = { 7 | source = "oracle/oci" 8 | version = ">= 4.115.0" 9 | } 10 | } 11 | required_version = ">= 1.0.0" 12 | } 13 | --------------------------------------------------------------------------------