System users in OCI

Sven Illert -

Once you are hosting an application in some environment, doesn’t matter if on-premises or in the cloud, you want to get notified by the application when soemthing happens or you need to take action. As an example let’s assume that may be a GitLab community edition you manage yourself in the Oracle Cloud Infrastructure. For this purpose there’s an Email Delivery Service which you can use to send mails from your cloud applications. For this to work you have to configure DKIM and SPF records for a DNS domain and configure aproved sender email addresses that may be used by your application. Maybe I’ll cover that in another blog post but that shouldn’t be addressed here now.

So far so good, that’s the easy part. But to use this email adress you can’t just let your application connect to the SMTP server provided by the OCI, you also have to authenticate to that. The credentials for the server are created for actual identity domain users and you can find those in your account profile as pictured below.

Creating SMTP credentials for Email Delivery Service

Creating SMTP credentials for Email Delivery Service

That may be handy if you really in person want to use the email delivery service and not anybody else or there won’t be any shift in responsibilities. But with the aforementioned GitLab example that may be not the case. The GitLab installation is not a real person and so may not have it’s own account in the identity domain. So how do you chose in which users profile you will create the SMTP credentials? If you create them in your admin account and you move responsibilities to some other person or even get removed from that tenant you probably want to avoid that you have to change all applications that are using your personal SMTP credentials.

Let’s think about that further. There’s not only emailing hat may be affacted, but also other profile bound authentication schemes. If you have a machine outside of the OCI that has scheduled tasks that manage resources in the OCI – like automated start/stop of some database – then you probably don’t want to put your personal API key there. This system might be accessed by other persons and so it would be exposed to them and could hand over administrative rights they should not be able to get. That’s another use case for a system user in the OCI that might get only those permissions to achive the designated task and not more.

It’s of course easy to create a new user in your default domain and reduce it’s capabilities like removing the possibility to set a local password. But I would to go a little bit further and create a new identity domain to have them separated. That makes administration of these users a bit more easy. You can prevent the login to this domain by not showing it as an option in the domain selection dialog. Also you can disable that accounts in that domain have to provide an email address which makes management of these accounts easier. The whole goal is to create a user that is not able to login, has no password and only has the capabilities that are needed to execute it’s designated task.

Below is what I’d do for the GitLab example. This creates a new free domain named System, a user named gitlab and a group named grp-email. The domain is hidden at login and does not require an email address for an account. The user has the possibility to create SMTP credentials only. Aside from these identitiy domain objects I also create a policy that allows members of the System/grp-email group to use the email-family services in the according compartment.

res# ource "oci_identity_domain" "dom-system-user" {
  compartment_id            = module.iam.compartments.operation.id
  display_name              = "System"
  description               = "Domain specific for system users"
  license_type              = "free"
  home_region               = "eu-frankfurt-1"
  is_hidden_on_login        = true
  is_primary_email_required = false
  is_notification_bypassed  = true
}

resource "oci_identity_domains_user" "su-gitlab" {
  schemas = [
    "urn:ietf:params:scim:schemas:core:2.0:User",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:userState:User",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:OCITags",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:capabilities:User",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:user:User"
  ]
  idcs_endpoint = oci_identity_domain.dom-system-user.url
  user_name     = "gitlab"
  name {
    given_name  = "gitlab"
    family_name = "system"
  }
  urnietfparamsscimschemasoracleidcsextensioncapabilities_user {
    can_use_api_keys                 = false
    can_use_auth_tokens              = false
    can_use_console_password         = false
    can_use_customer_secret_keys     = false
    can_use_db_credentials           = false
    can_use_oauth2client_credentials = false
    can_use_smtp_credentials         = true
  }
}

resource "oci_identity_domains_group" "sg-email" {
  idcs_endpoint = oci_identity_domain.dom-system-user.url
  display_name  = "grp-email"
  schemas = [
    "urn:ietf:params:scim:schemas:core:2.0:Group",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:dynamic:Group",
    "urn:ietf:params:scim:schemas:oracle:idcs:extension:OCITags"
  ]
}

resource "oci_identity_policy" "pol-email-use" {
  name           = "pol-email-use"
  compartment_id = oci_identity_compartment.cp-root.id
  description    = "Policy for users of the email delivery service"
  statements = [
    "Allow group ${oci_identity_domain.dom-system-user.display_name}/${oci_identity_domains_group.sg-email.display_name} to use email-family in compartment ${module.iam.compartments.operation.name}"
  ]
}

As you may have noticed this code does not assign the user to the group. As of now (August 2024) there seems to be a bug in the OCI api that terraform and the oci cli use which prevents the assignment of a user to a group when they are not the default domain. But I’m in contact with Oracle in a SR to figure out how to do that.

The other part that is missing above is the SMTP credential it self. Since it provides a password it is only accessible in the OCI console with your browser as shown above. Make sure you copy the password to a password manager of your choice before closing that dialog that shows it to you as it cannot be changed or shown afterwards anymore.

Hope this helps!