Creating API credentials for certbot-dns-oci

in Cloud & Serverless


The setup

You want to generate Letsencrypt certificates using DNS-01 challenge (e.g. wildcard certificates) and you host your domain on Oracle Cloud. Your code is in Python and you want to use certbot-dns-oci for updating the TXT DNS records for the DNS-01 challenge.

The problem

You need to provide some OCI credentials to certbot-dns-oci and it's not obvious where and how do you get them.

Here's what certbot-dns-oci says:

--dns-oci-credentials has special value instance_principal that switches certbot to use the instance principal for OCI authentication (please, read the documentation about the feature.) Corresponding dynamic group must be able to read dns-zones in compartment and manage dns-records.

In other cases, plugin requires the OCI credentials configuration file, which is ~/.oci/config by default. The profile can be specified by --dns-oci-profile (usually DEFAULT).

The credentials

1. Create user, group and policy

  1. Go to OCI console → Identity & SecurityDomains Domains here means Identity Domains. Every tenancy has at least one, usually named “Default”.
  2. Open the domain and click the User management tab
  3. Under Groups click Create. Name the group e.g. DNS Managers (can be any name you want). Once created, copy the group OCID to use in step 4
  4. Under Users click Create. Uncheck Use email as username. Provide username and last name (can be the same). Assign user to the DNS Managers group
  5. Go to OCI console → Identity & SecurityPolicies. Create new policy with statement:

    Allow group id OCID to manage dns in tenancy

    Use the OCID for the group you created, e.g. ocid1.group.oc1.abc...def. Here's documentation on policy syntax.

2. Get API keys

  1. Open the newly created user and click API keys
  2. Click Add API key
  3. Since Generate API key pair is selected by default, you can download the private and public keys right away
  4. Once the keys are downloaded, you can click Add to proceed

3. Create configuration file

You will get the Configuration file preview screen where it shows your key fingerprint and the template to create an .ini configuration file.

The template will look like this:

[DEFAULT]
user=ocid1.user.oc1.abc...def
fingerprint=ab:cd:...:ef
tenancy=ocid1.tenancy.oc1.abc...def
region=<your-region-here, e.g. `us-ashburn-1`>
key_file=<path to your private keyfile> # TODO

Each key is documented in SDK and CLI Configuration File → File Entries.

Test user

Use Cloud Shell right in OCI Console. You will have to upload the .pem and the .ini and then issue some dns command using these credentials to see if they work.

On top right click Developer Tools → Cloud Shell. You get something that looks like SSH in your browser.

mkdir -p ~/.oci
vi ~/.oci/config

Paste your .ini contents into ~/.oci/config. Gotchas:

  • replace [DEFAULT] with username we're testing, e.g. api_dns_user
  • replace key_file with where the private key will actually be, e.g. ~/.oci/api_dns_user.pem
  • ensure chmod 600 ~/.oci/config and chmod 600 ~/.oci/api_dns_user.pem, else it will complain permissions are too open

Lastly, you will need your compartment OCID. You can get it in Cloud Shell:

oci iam compartment list --all --include-root --query "data[?\"compartment-id\"==null].id | [0]" --raw-output

Now we can test the credentials:

oci --auth api_key --config-file ~/.oci/config --profile api_dns_user dns zone list --compartment-id COMPARTMENT_OCID

Bonus points

If you're automating deployment, you will need to store the private key only.

The fingerprint can be easily derived by using:

openssl rsa -pubout -outform DER -in "/path/to/private-key.pem" 2>/dev/null | openssl md5 -c | awk '{print $2}'

If you don't use awk '{print $2}' the output will be MD5(stdin)= ab:cd:...:ef

#oracle-cloud-infrastructure #certbot