Authorization Hub integration
Authorization Hub is Axiomatics' control plane system for authorization domains, policies, attributes, and attribute connectors. It stores policies and configurations that ADS retrieves for policy evaluation.
By connecting APD to Authorization Hub you can:
- push and pull the attribute dictionary, attribute connectors and ALFA policies, so you can view and edit them in Authorization Hub
- push, pull and promote the authorization domain built by APD, which ADS loads from Authorization Hub
- run ADS locally, and your system tests, with a domain loaded from Authorization Hub
As a delivery model, APD pushes the tested domain to Authorization Hub, and your ADS instances load it from there, see Configure ADS to load the domain from Authorization Hub. The other tasks integrate your APD project with the work done in Authorization Hub.
APD supports Authorization Hub 26.2 and later. A successful push is live in Authorization Hub immediately. If Authorization Hub rejects content, the task fails, and the rejected content is not stored.
In Authorization Hub, an authorization domain is identified by a project and a domain name.
Configuration
To connect to Authorization Hub, add a hub block within the repositories section in your build.gradle file.
alfa {
repositories {
hub {
host 'https://hub.dev.myorg'
project 'Project 1'
domainName 'domain1'
envVariable 'LDAP_PIP_URL', 'http://ldap-dev.myorg.com'
oidcCredentials {
client_id 'apd'
client_secret System.getenv('HUB_CLIENT_SECRET')
}
}
}
}
Do not write secrets such as client_secret in build.gradle, as the file is committed to your Git repository. Read them from environment variables with System.getenv('<name>'), as in the example above, and set the variables in your shell or as secrets of your CI pipeline:
export HUB_CLIENT_SECRET='<secret>'
| Property | Description |
|---|---|
host | Required. Protocol and hostname of Authorization Hub. |
project | Required. The Authorization Hub project. Until APD version 27.1, a connection without project still works with a warning, see the note below the table. |
domainName | Required. The domain name in Authorization Hub. |
environment | Optional. Names the Gradle tasks of this connection, for example dev gives AllPushTodev and the task group axiomatics-hub-dev. It has no effect on the connection itself. Default: <project>_<domainName>, for example Project_1_domain1. Use it when you connect to several Authorization Hubs, for example a development and a production Authorization Hub: the task names then show which Authorization Hub they use. It is required when two connections have the same project and domain name. |
envVariable | Optional. Sets an environment variable of the local ADS that APD starts with this domain (runAdsWith… and test…, see ADS and system tests). Add one envVariable 'KEY', 'VALUE' line per variable. It is used only by APD: it has no effect on the domain pushed to Authorization Hub, nor on the ADS of your deployments. |
client_id | Required. The client ID to use for OIDC authentication to Authorization Hub. |
client_secret | Required. The client secret to use for OIDC authentication to Authorization Hub. Read it from an environment variable. |
realm | Optional. The OIDC realm used to get the access token: hub (default) for Authorization Hub, asm for ASM (see ASM and standalone ADM). Set another value only if your identity provider uses a custom realm. |
tokenUri | Optional. The path of the OIDC token endpoint, relative to host, if it differs from the default /auth/realms/<realm>/protocol/openid-connect/token. |
Authorization Hub requires oidcCredentials { }.
The paths of the Authorization Hub API cannot be changed. If Authorization Hub is behind a gateway or proxy, it must forward the paths /api/… and /auth/… unchanged.
:::warning Deprecated
Setting the project for all connections in the alfa { } section, with project 'name' or namespace 'name', is deprecated and will be removed in APD version 27.1. Set project in each hub { } block instead. Until then, a connection without project uses the one in the alfa { } section or, if none is set, the name of the Gradle project, and APD prints a warning.
:::
Several Authorization Hub connections
Add one hub block per Authorization Hub, project or domain, for example one per environment. APD creates the tasks of each connection, and tasks to promote a domain from a connection to every connection declared after it (see Tasks).
alfa {
repositories {
hub {
environment 'dev'
host 'https://hub.dev.myorg'
project 'Project 1'
domainName 'domain1'
oidcCredentials {
client_id 'apd'
client_secret System.getenv('HUB_DEV_CLIENT_SECRET')
}
}
hub {
environment 'prod'
host 'https://hub.prod.myorg'
project 'Project 1'
domainName 'domain1'
oidcCredentials {
client_id 'apd'
client_secret System.getenv('HUB_PROD_CLIENT_SECRET')
}
}
}
}
Use environment when you connect to several Authorization Hubs, so that the task names show which one they use, for example DomainPromoteFromdevToprod. Here it is also required: both connections have the same project and domain name, and the build fails if two connections get the same task names.
Task group
Each connection gets its own Gradle task group axiomatics-hub-<environment> in lowercase, for example axiomatics-hub-dev. Without environment, the default name is used: project 'Project 1' and domainName 'domain1' give axiomatics-hub-project_1_domain1. The group contains the tasks to push, pull and promote, and to run ADS and the tests with the domain of this connection. They are described in Tasks. Run ./gradlew tasks to list them.
ASM and standalone ADM
:::warning Deprecated Out-of-the-box support for ASM 7, ASM 6 and a standalone ADM is deprecated and will be removed in APD version 27.1. Use Authorization Hub. :::
To connect to ASM or a standalone ADM, use an adm block. Only the domain tasks and the ADS tasks are available. The dictionary, attribute connector and policy tasks are for Authorization Hub only. The task group is axiomatics-asm-<environment>.
alfa {
repositories {
// ASM: OIDC authentication in the realm asm
adm {
environment 'asm'
host 'https://asm.myorg'
project 'MyNamespace'
domainName 'domain1'
realm 'asm'
oidcCredentials {
client_id 'apd'
client_secret System.getenv('ASM_CLIENT_SECRET')
}
// Optional, only if the ADM API is on other paths. %s is replaced by the namespace, then the domain name.
// apiUrlPushAsmTemplate '/api/adm/namespaces/%s/names/%s'
// apiUrlPullAsmTemplate '/api/adm/namespaces/%s/names/%s/domain'
}
// Standalone ADM: basic authentication
adm {
environment 'adm'
host 'https://adm.myorg'
project 'MyNamespace'
domainName 'domain1'
basicCredentials {
username 'apd'
password System.getenv('ADM_PASSWORD')
}
// Optional, only if the ADM API is on other paths. %s is replaced by the namespace, then the domain name.
// apiUrlPushStandaloneTemplate '/adm/namespaces/%s/names/%s'
// apiUrlPullStandaloneTemplate '/adm/namespaces/%s/names/%s/domain'
}
}
}
| Property | Description |
|---|---|
project | Required. The ASM or ADM namespace. |
realm | For ASM, set asm. |
oidcCredentials { } | For ASM: client_id and client_secret, as for Authorization Hub. |
basicCredentials { } | For a standalone ADM: username and password. Read the password from an environment variable. |
apiUrlPushAsmTemplate, apiUrlPullAsmTemplate | Optional, with oidcCredentials. The paths, relative to host, to push and pull a domain. Defaults as in the example. |
apiUrlPushStandaloneTemplate, apiUrlPullStandaloneTemplate | Optional, with basicCredentials. The paths, relative to host, to push and pull a domain. Defaults as in the example. |
The other properties (host, domainName, environment, envVariable, tokenUri) are the same as for hub.
Certificates
If the certificate of Authorization Hub is not trusted by the Java runtime that runs Gradle, add it to the truststore of the operating system or of Java. Alternatively, specify a custom truststore (JKS or PKCS12 format) with the standard Java system properties in gradle.properties:
systemProp.javax.net.ssl.trustStore=mycacerts.jks
systemProp.javax.net.ssl.trustStorePassword=changeit
systemProp.javax.net.ssl.trustStoreType=JKS
or on the command line:
./gradlew -Djavax.net.ssl.trustStore=mycacerts.jks …
Restart the Gradle daemon with ./gradlew --stop after changing these settings, otherwise they may not be applied.
Tasks
The task names below are for a connection with environment 'dev' and domainName 'domain1', and a second connection prod (see Several Authorization Hub connections). Run ./gradlew tasks to see the names in your project.
Authorization domain
These tasks work with the authorization domain that APD builds and that ADS loads. They are available for Authorization Hub, ASM and standalone ADM.
| Task | What it does |
|---|---|
DomainPushTodev | Builds the domain (buildAuthzDomain) and stores build/alfa/domain/ads/domain.yaml unchanged as the domain domain1, so the domain you tested is the domain ADS loads. Live immediately. |
DomainPullFromdev | Pulls the domain domain1 to build/alfa/axiomatics-hub-dev/domain.yaml. The policies in it are XACML. To get the ALFA sources, use PolicyPullFromdev. |
DomainPromoteFromdevToprod | Pulls the domain from dev and pushes it unchanged to prod. There is a promote task from each connection to every connection declared after it in build.gradle. |
printHubConnections | One task for all connections: prints how an ADS loads the domain of each connection, and the identity and metadata of that domain. See Configure ADS to load the domain from Authorization Hub. |
Domains pushed by APD are available to ADS (see Configure ADS to load the domain from Authorization Hub), but do not appear in the domain list of the Authorization Hub UI.
AllPushTodev pushes the sources of the domain: the attribute dictionary, the attribute connectors and the ALFA policies (see Dictionary, attribute connectors and policies). It does not push the built domain. Run DomainPushTodev to push the built domain.
Dictionary, attribute connectors and policies
These tasks are available for Authorization Hub only.
| Push | Pull | Local files |
|---|---|---|
DictionaryPushTodev | DictionaryPullFromdev | src/authorizationDomain/attributes.yaml |
AttributeConnectorsPushTodev | AttributeConnectorsPullFromdev | src/authorizationDomain/attributeConnectors/, one YAML file per connector |
PolicyPushTodev | PolicyPullFromdev | src/authorizationDomain/alfaSpecifications/ |
AllPushTodev: all three, in this order | AllPullFromdev: all three, in this order, then regenerates the ALFA and Java dictionaries |
Push: Git is the source of truth: what exists in Authorization Hub is updated, what is missing is created, and nothing is deleted. Each push is stored in Authorization Hub with the change message <task name>: <Git commit>, for example PolicyPushTodev: 1a2b3c4 (-dirty is added when the working tree has uncommitted changes), so you can trace each change back to Git.
- Push the dictionary before the attribute connectors: the attributes a connector uses must exist in Authorization Hub.
- If Authorization Hub rejects an attribute,
DictionaryPushTodevlogs the reason and continues with the next one. When all attributes have been tried, the task fails and lists the rejected attributes. The other attributes are pushed.
Pull: The dictionary is merged into attributes.yaml: existing attributes are updated, new ones added, and attributes only in the file are kept. Attribute connector and policy files are overwritten. The pull tasks refuse to overwrite files with uncommitted changes. To pull anyway, add -Dapd.allowUnsafe=true.
DictionaryPullFromdev only updates attributes.yaml. To update the ALFA and Java dictionaries after it, run the local tasks generateAlfaDictionaryFromYaml and generateJavaDictionaryFromYaml, for example ./gradlew DictionaryPullFromdev generateAlfaDictionaryFromYaml generateJavaDictionaryFromYaml. AllPullFromdev runs them for you. See Gradle tasks.
Policies in Authorization Hub: The policies are pushed to the policy package policypackage of the project, which you can view and edit in the Authorization Hub policy editor.
- Folders become part of the name, with
__as separator:consultants/main.alfais pushed asconsultants__main.alfa, and pulled back toconsultants/main.alfa. attributes.alfa,system.alfaandattribute-dictionary.alfaare not pushed, andattribute-dictionary.alfais not pulled.- If the policy package does not exist, it is created with a placeholder
attribute-dictionary.alfa, which the policy editor needs. Files that only exist in Authorization Hub are kept.
ADS and system tests
These tasks start a local ADS that loads the domain domain1 from the connection. They are available for Authorization Hub, ASM and standalone ADM.
| Task | What it does |
|---|---|
runAdsWithdev-domain1 | Starts ADS on a random local HTTP port and keeps it running until you stop it with Ctrl-C. The port is printed when ADS has started. |
testdev-domain1 | Starts ADS, runs your system tests against it, and stops ADS. The test report is in build/reports/tests/testdev-domain1. |
- ADS uses basic authentication: username
pdp-user, passwordsecret. - Add environment variables of this ADS with
envVariable 'KEY', 'VALUE'in thehubblock. - ADS writes its output to a log file, whose path is printed. Open the file to see the ADS log.
- Set
mainpolicyin thealfasection of yourbuild.gradlefile.buildAuthzDomainfails ifmainpolicyis not a top-level policy or policy set. - The helper tasks
spawnAdsWithdevdomain1,waitToStartAdsdevandstopAdsFordevstart, wait for and stop this ADS. They are in the groupotherand run automatically.
Deprecated task names
For adm connections (ASM and standalone ADM), these task names still work, in the group other, but print a warning:
| Deprecated | Use instead |
|---|---|
pushTo<environment> | DomainPushTo<environment> |
pullFrom<environment> | DomainPullFrom<environment> |
promoteFrom<source>To<target> | DomainPromoteFrom<source>To<target> |
Configure ADS to load the domain from Authorization Hub
Your ADS can load the domain that DomainPushTodev stores directly from Authorization Hub. To get the settings, run:
./gradlew printHubConnections
For each connection, it prints the client id, the token URI and the URL of the domain (path), then downloads the domain and prints its identity and metadata, so you can check which Git commit it was built from. The client secret is never printed. For example:
AuthHub dev (project MyProject, domain domain1)
client-id: apd
token-uri: https://hub.example.com/auth/realms/hub/protocol/openid-connect/token
path: https://hub.example.com/api/adm/namespaces/<project id>/names/domain1/domain
current domain identity: <domain id>
domain-metadata: Git-Identity: my-repo-1a2b3c4
...
- If the domain has not been pushed yet, the task prints
no domain content available. The URL is still the one to use. - If a connection cannot be reached or the login fails, the task prints the error, continues with the other connections, and fails at the end.
DomainPushTodevalso prints the URL of the domain after each push.
Set the environment variable ADS_DOMAIN of ADS to the URL, or set it as path in deployment.yaml. ADS gets an access token from Authorization Hub with the OAuth 2 client credentials grant. In deployment.yaml, uncomment the authentication section under domain and the oauth2 section under spring.security (projects created with APD 26.2 or later), or add them. Replace hub.example.com in token-uri with the host of your Authorization Hub:
domain:
path: ${ADS_DOMAIN:./domain.yaml}
refreshInterval: 30 seconds
authentication:
oauth2ClientId: authhub
spring:
security:
user:
name: ${ADS_USERNAME:pdp-user}
password: ${ADS_PASSWORD:secret}
oauth2:
client:
registration:
authhub:
client-id: ${ADS_DOMAIN_CLIENT_ID}
client-secret: ${ADS_DOMAIN_CLIENT_SECRET}
scope: openid
authorization-grant-type: client_credentials
provider: authhub
provider:
authhub:
token-uri: https://hub.example.com/auth/realms/hub/protocol/openid-connect/token
| Environment variable | Value |
|---|---|
ADS_DOMAIN | The URL printed by printHubConnections or DomainPushTodev. |
ADS_DOMAIN_CLIENT_ID, ADS_DOMAIN_CLIENT_SECRET | An Authorization Hub client that can read the domains of the project. Use a separate client for ADS, not the client of your pipeline. Set the secret from a secret store, for example a Kubernetes Secret. |
With refreshInterval, ADS loads each domain that DomainPushTodev or DomainPromoteFromdevToprod stores within the interval, without a restart. ADS does not start if it cannot load the domain. If Authorization Hub cannot be reached later, ADS keeps the last valid domain. See Configure ADS to reload the domain for the details of refreshInterval.
If the certificate of Authorization Hub is not trusted by the Java runtime of ADS, configure a TLS configuration and set tlsConfigurationId in the authentication section. See Runtime domain updates in the ADS documentation.