The most recent patch for this version is 26.2.1.  Learn more

Skip to main content

Sample CI/CD pipeline

A key principle of policy DevOps is that authorization policy changes go through the same automated quality gates as application code. When a developer modifies a policy, attribute, or attribute connector, the CI/CD pipeline verifies the change with tests and then delivers the authorization domain to ADS.

How the domain reaches ADS depends on your delivery model. Every pipeline begins with testing, but delivery steps differ:

Delivery modelAfter ./gradlew testA policy change reaches ADS by
Authorization HubPush the domain and its building blocks to Authorization HubADS loading the domain from Authorization Hub
Container imageStage the build context, build and push the ADS imageDeploying the new image
Custom deliveryDeliver domain.yaml to storage that ADS readsADS reloading the file

See Integration and delivery to choose a delivery model. The models can be combined, for example Authorization Hub for development and test, and container images for production.

Before you start​

Gradle downloads APD and ADS from the Axiomatics repository. Store the access keys as secrets of your CI/CD system and expose them to the build as the environment variables AXIOMATICS_ACCESS_KEY_ID and AXIOMATICS_SECRET_ACCESS_KEY. Do the same for every other secret the delivery needs, such as an Authorization Hub client secret. Never write secrets in build.gradle or the pipeline file.

The examples below show the steps only. Add the checkout, Java setup, and secrets as usual in your CI/CD system.

Authorization Hub​

APD pushes the domain and its building blocks to Authorization Hub, and ADS loads the domain from there. The image does not change when a policy changes. See Authorization Hub integration for the configuration and all tasks.

The examples use the two connections dev and prod from Several Authorization Hub connections, which read their client secrets from HUB_DEV_CLIENT_SECRET and HUB_PROD_CLIENT_SECRET.

# 1. Run unit and integration tests against the authorization domain
./gradlew test

# 2. Push the dictionary, attribute connectors and policies, and the domain ADS loads, to dev
./gradlew AllPushTodev DomainPushTodev

# 3. Later, for example after an approval: copy the domain tested in dev to prod
./gradlew DomainPromoteFromdevToprod
  • AllPushTodev pushes the dictionary, attribute connectors and policies, so you can view and edit them in Authorization Hub. DomainPushTodev pushes the domain that APD built and tested, which ADS loads.
  • A successful push is live immediately. A push fails when Authorization Hub rejects the content.
  • Run the pipeline on a committed Git tree: the change message stored in Authorization Hub then contains the commit, without -dirty.
  • DomainPromoteFromdevToprod copies the domain unchanged, so production gets exactly the domain that was tested in dev. It needs the secrets of both connections.
Jenkinsfile
pipeline {
agent any
stages {
stage('Test') {
steps {
sh './gradlew test'
}
}
stage('Push to dev') {
steps {
withCredentials([string(credentialsId: 'hub-dev-client-secret', variable: 'HUB_DEV_CLIENT_SECRET')]) {
sh './gradlew AllPushTodev DomainPushTodev'
}
}
}
stage('Promote to prod') {
input {
message 'Promote the domain from dev to prod?'
}
steps {
withCredentials([string(credentialsId: 'hub-dev-client-secret', variable: 'HUB_DEV_CLIENT_SECRET'),
string(credentialsId: 'hub-prod-client-secret', variable: 'HUB_PROD_CLIENT_SECRET')]) {
sh './gradlew DomainPromoteFromdevToprod'
}
}
}
}
}

Container image​

The authorization domain is baked into the ADS container image: every policy change gives a new, versioned image. See Container image. The examples tag the image with the Git commit, the same commit as in the identity of the domain, so you can trace an image back to the commit it was built from.

# 1. Run unit and integration tests against the authorization domain
./gradlew test

# 2. Stage the ADS deployment build context
./gradlew stageDeployment

# 3. Build the container image
docker build -t <registry>/<image>:<git commit> build/install/deployment/ads/

# 4. Push the image to your registry
docker push <registry>/<image>:<git commit>
Jenkinsfile
pipeline {
agent any
stages {
stage('Test') {
steps {
sh './gradlew test'
}
}
stage('Stage deployment') {
steps {
sh './gradlew stageDeployment'
}
}
stage('Build and push image') {
steps {
sh '''
docker build -t ${REGISTRY}/${IMAGE}:${GIT_COMMIT} build/install/deployment/ads/
docker push ${REGISTRY}/${IMAGE}:${GIT_COMMIT}
'''
}
}
}
}

Custom delivery​

APD builds domain.yaml, and the pipeline delivers it to storage that ADS reads: a shared drive, a Kubernetes volume, a server, or a repository. ADS reloads the domain when the file changes, so the image does not change when a policy changes. See Custom delivery for the ADS configuration and the delivery alternatives.

# 1. Run unit and integration tests against the authorization domain
./gradlew test

# 2. Build the domain and deliver it with your own Gradle task, see Custom delivery
./gradlew deployDomain

deployDomain is a task you add to build.gradle. It depends on buildAuthzDomain and delivers build/alfa/domain/ads/domain.yaml, for example by copying it to a shared drive. You can also deliver the file with a pipeline step instead, after ./gradlew buildAuthzDomain.

Jenkinsfile
pipeline {
agent any
stages {
stage('Test') {
steps {
sh './gradlew test'
}
}
stage('Deliver domain') {
steps {
sh './gradlew deployDomain'
}
}
}
}