IAM Configuration Best Practices

IAM Configuration Best Practices

Intro

In modern Continuous Delivery setups it is typical to build binaries such as code libraries or Docker images once, when code changes, then combine binaries with environment specific configuration at deployment time. This separation also enables you to spin up a completely new environment at any time, by simply adding new configuration.

GitOps Deployment

When using OAuth and OpenID Connect, many intricate settings are outsourced from your applications, and instead managed by the Identity and Access Management (IAM) system. This complex component then needs to be deployed down a pipeline in the same manner as your other applications.

Identity Data v Configuration

Some information clearly needs to be different for each stage of the pipeline, such as user accounts and passwords, token storage, session data and audit information. This is the identity data, and is typically stored in a SQL or NoSQL database.

Other information, such as the following OAuth client settings for an application, are likely to be the same for all stages of the pipeline, with only a minority of values that vary, such as URLs and client secrets. This is the identity configuration.

<client>
  <id>spa-client</id>
  <client-name>spa-client</client-name>
  <description>Demo Single Page Application</description>
  <secret>$5$TCfYst/ysngW7RbV$rMLasvlJpnQ0wmFoeTrdIHPjVdnsqOVelkqawZ.fZ17</secret>
  <redirect-uris>https://www.example.com</redirect-uris>
  <access-token-ttl>600</access-token-ttl>
  <refresh-token-ttl>7200</refresh-token-ttl>
  <scope>openid</scope>
  <scope>profile</scope>
  <capabilities>
    <code>
    </code>
  </capabilities>
</client>

The IAM system must also protect certain values, using encryption or secure hashes, as for the client secret value above. The crypto used is not as simple as just SSL keys and certificates, since crypto will also be part of the application settings when more secure flows are used. Therefore crypto values should be considered part of your identity configuration.

Finally, any good IAM system provides extensibility features, to specialize the OAuth behavior. These might be implemented as scripts, which are also part of your identity configuration. The custom logic might be used for purposes such as account linking or including custom claims in tokens returned to applications.

Maintainable Configuration

Firstly, an IAM system should enable you to avoid duplication of configuraton data. As an example, the following XML snippet shows how Parameterized Configuration is expressed in the Curity Identity Server:

<client>
  <id>spa-client</id>
  <client-name>spa-client</client-name>
  <description>Demo Single Page Application</description>
  <secret>#{WEB_CLIENT_SECRET}</secret>
  <redirect-uris>#{WEB_BASE_URL}</redirect-uris>
  <access-token-ttl>600</access-token-ttl>
  <refresh-token-ttl>7200</refresh-token-ttl>
  <scope>openid</scope>
  <scope>profile</scope>
  <capabilities>
    <code>
    </code>
  </capabilities>
</client>

Secondly, it should be possible to manage the configuration information in an understandable way as it grows. In some organizations the IAM system will need to provide multiple endpoints or profiles, to support usage in larger organizations with subdivisions.

It should therefore be possible to split the configuration into modular parts that are easy to understand in isolation. The configuration data might initially be managed by separating it into the following files, if an XML storage format is used:

base.xml
crypto.xml
authenticationprofile.xml
tokenprofile.xml

Environment Specific Data

The main configuration can now be deployed to multiple stages of your pipeline, such as DEV, STAGING and PRODUCTION. In each case you will need to complete the configuration with environment specific values. Firstly you will have plaintext values such as Redirect URIs. These environment values, and any custom scripts, are best managed alongside the configuration. A file layout similar to the following could be used:

base.xml
crypto.xml
authenticationprofile.xml
tokenprofile.xml
scripts/mycustomscript.js
dev.env
staging.env
production.env

Each .env file might contain fields such as these. At deployment time these will become environment variables on the deployed servers or containers for the IAM system:

RUNTIME_BASE_URL='https://idsvr.example-dev.com:8443'
DB_USERNAME='dbuser'
WEB_BASE_URL='https://web.example-dev.com'

Secure values such as those below cannot be deployed as plain environment variables, since they reveal important secrets. Instead these values need to be encrypted or securely hashed before they become environment variables, as in the following example. These values need to be managed differently to the other configuration data, as discussed later in this article.

ADMIN_PASSWORD='$5$uquoeYRe$GLtb4BhlI4HMAB7bScW7r6CETdFhM6DKyRoQdev3EqC'
DB_CONNECTION='data:text/plain;aes,v:S.UWVaUGR1N1JwN2JC ...'
DB_PASSWORD='data:text/plain;aes,v:S.Nzl1UGVRZklDVlNMMGRDSw==.2JiZkUjJKhlvYQoMH ...'
WEB_CLIENT_SECRET='$5$.T/sE5LWsmRoD3xb$hL7dXaOV8WEKVRZeMuPlM6oFYFD7PH1UmUUHsirjaG1'
SYMMETRIC_KEY='data:text/plain;aes,v:S.NzhhTTA3TWlHZ1BtSEJacg==.6xaTrU ...'
SSL_KEY='data:application/p12;aes,v:S.THcyaW9XUzRxakpGZzMwcQ==.MPKK96RQ9z6 ...'
SIGNING_KEY='data:application/p12;aes,v:S.bFRjcXpBY3hmSHREYXpBUg==.YdBLTdZTGlW ...'
VERIFICATION_KEY='data:application/pem;aes,v:S.YUJnaGcxT0U5MjJjdTlQZQ==.RmC3nWa6x4 ...'

Safe Upgrades and New Environments

Companies should ensure that they can use shared IAM configuration, and also that they can quickly generate environment specific IAM settings. You then simply need to keep values up to date, after which you can quickly upgrade any stage of the pipeline, or spin up a completely new stage when needed.

In many organizations, architects and developers from engineering teams have the best understanding of settings used for OAuth flows. They are responsible for populating the configuration values, and may then roll the system out to stages such as DEV, TEST1, TEST2, PLATFORMTEST, and LOADTEST. This will include upgrading the IAM system to a new version, a few times every year.

Other stakeholders, including DevOps, will also review and provide feedback on some areas of security configuration. The DevOps team might then be responsible for promoting the latest configuration to STAGING and PRODUCTION. By using shared configuration, the deployment risks are significantly reduced for these rollouts.

IAM Configuration as Code

Many companies follow an infrastructure as code approach, so that important configuration is managed in source control. Your identity configuration should also fit into this process, where the below file list could be stored in a Git repository, which then becomes the source of truth for your identity configuration. The Git repository also provides an audit trail of how the configuration has changed over time:

base.xml
crypto.xml
authenticationprofile.xml
tokenprofile.xml
scripts/mycustomscript.js
dev.env
staging.env
production.env

Secrets should not be checked into source control, and should instead be stored in a secure vault, such as that provided by your cloud platform. When secrets change, they must be changed in the vault. On the next deployment, your continuous delivery system must then be able to recreate the secure environment variables from the latest secrets.

GitOps Change Management

In an IAM system, the configuration will change often, whenever you add an application, implement a new flow, or add custom scripts that extend the base OAuth behavior.

The most user friendly way to change configuration is often in the Admin UI provided by the IAM system, where the meanings of settings are visually explained. This is typically done in Engineering stages of the pipeline, so you may not even need an Admin UI for the production stage.

Configuration Changes

The IAM system should provide some kind of event that you can subscribe to when configuration changes. You can then implement logic to save changes made in the Admin UI back to the Git repository. The following type of GitOps process can then be followed, where all changes to the IAM configuration undergo people reviews:

Pull Request Automation

Since the configuration data has no encrypted values, the Git differences will be clean and easy to review, providing an audit trail of how the configuration has changed over time:

Pull Request

For production stages of your pipeline, the deployment system will typically download identity configuration for a specific Git Tag, representing the last signed off production release. Engineering stages of the pipeline will instead use a less stable tag, when new security features are being developed and tested.

Conclusion

Managing deployment of the intricate security settings for your software platform is not a trivial problem, and requires the IAM system to have a solid architectural design. The end result should avoid duplication of the many security settings, and enable you to manage them reliably over time. This must also work well for people and integrate with modern continuous delivery best practices.

All of the behaviors described in this article are all supported by the Curity Identity Server, and described in our Configuration Guides. The GitOps Configuration Management tutorial provides an end-to-end worked example that can be run on a development computer. It uses parameterized and split configuration, along with automated Git pull requests, and some helper resources to show how secure environment variables can be managed.