If you are operating as a service provider and your are in the lead for managing multiple OCI tenants you would like to be efficient and in control of all the tenants. In my case I am responsible of managing a handful tenants and I am choosing to manage my tenants using Terraform and storing my Terraform code in a local installed GitLab installation. Every tenant has its own GitLab repository.
When I make changes to my code I push them them to GitLab and because of a pipeline that is configured, the new version will be pushed to an OCI Management server. That server has all the things needed to manage the OCI tenants. In this post I will show you my setup.
The server
For the management server I choose to use an Oracle Linux 9 installation. For managing the tenants there are two major things installed. The OCI-CLI and Terraform. Please refer to the documentation of Oracle and Hashicorp for the installation instructions.
My pipeline in gitlab copies all the terraform files to /opt/terraform/[repo]. As mentioned above, every tenant uses its own repository.
OCI-CLI
When the installation of the OCI-CLI is completed it is time to configure it. Assuming the all the defaults are kept in place all the configuration is placed in /root/.oci . Within the file config you can configure all your tenants. As the documentation says, you need to configure API keys as well to connect to the tenant. As I like to have a “clean” server I place all my keys for connecting in /root/.oci/keys/[tenant].
You configuration file should look something like this then:
[DEFAULT]
user=ocid1.user.oc1..xxxxxxxxxxxxxxxxxxxxx
fingerprint=[fingerprint]
key_file=/root/.oci/keys/default/key.pem
tenancy=ocid1.tenancy.oc1..aaaaaaaastt7xxxxxxxxxxxxxxxxxx
region=eu-amsterdam-1
[tenant1]
user=ocid1.user.oc1..xxxxxxxxxxxxxxxxxxxxx
fingerprint=[fingerprint]
key_file=/root/.oci/keys/tenant1/key.pem
tenancy=ocid1.tenancy.oc1..aaaaaaaas3apxxxxxxxxxxxxxxxxxx
region=eu-amsterdam-1
[tenant2]
user=ocid1.user.oc1..xxxxxxxxxxxxxxxxxxxxx
fingerprint=[fingerprint]
key_file=/root/.oci/keys/tenant2/key.pem
tenancy=ocid1.tenancy.oc1..aaaaaaaapgt5xxxxxxxxxxxxxxxxxx
region=eu-amsterdam-1
My recommendation is to create a specific user (service account) for your terraform connection which only has access to the API to make the attach surface as small as possible.
Terraform
But how does Terraform know then which tenant it needs to manage? Let me show you. In this case the only thing you we will look at, is the provider file. I always name it provider.tf. Every single tenant has its own file as Terraform works like that. When I would like to manage tenant1 for example, I can mention the specific configuration in the file. It should look something like this:
# Set pre-requisite confing
terraform {
required_version = ">= 0.12"
required_providers {
oci = {
source = "oracle/oci"
version = "7.30"
}
}
}
# Set provider and configration
provider "oci" {
config_file_profile = "tenant1" # Reference profile in oci-cli
As you can see, I reference the profile that I configured in the OCI-CLI. Those details will Terraform use to connect to the tenant.
Considerations
There are some things in the Terraform behavior and setup that requires some attention is this setup. It is not very complex, but you need to think about it.
- Make sure you safe your Terraform State file externally and not in the same folder. Git will overwrite it when doing a new merge in this case. Terraform is mentioning that it is NOT best practice to store your tfstate locally. In my case I use the backend http function in Terraform so it leverages the Terraform State function in my GitLab environment.
- When your run your terraform script for the first time, you need to run terraform init first so it downloads and configures the provider. It will download it in the folder of your terraform scripts in the .terraform folder. Same situation as in the previous bullet; When a new merge is done and the pipline runs, it will delete the .terraform folder. Make sure you add a .gitignore to your repository and configure it in your pipeline.
- Your network should be setup in a way that your OCI management server can do API calls to *.oraclecloud.com on port 443. So outgoing connections.
This way you can manage all your tenants from one place and still keep control. As the impact can be serious if you makes changes you would like to see what actually happens.
Hope this helps you in your setup 🙂 Happy engineering!