Audience
This document is intended for those managing and running AA in a SaaS as well as developers integrating with AA in the SaaS deployment.
Current SaaS Deployed Implementation
In the OpenText managed SaaS environments some customers may be have only AA, some may have limited access to AA for example IG customers, or they might have bought the greater CyberSecurity product family and be allowed full access to AA and every other CyberSecurity product. The functionality that is permitted and billed for is dependent on which product definitions are associated with a tenant.
IG customers may upgrade to full AA license, or may be given a trial license to full AA+risk, after the trial license expires they would revert back to a limited license.
Advanced Authentication SaaS Concepts
Products
In essence a product is an integration with a system, systems may be part of the AA product not enabled, external processes, or a contract to deliver functionality. Examples of products are Password management, Identity Governance, Licenses for RIsk, License for Federation and Single Sign On, and trial versions of AA.
Tenants may be associated with more than one product, each association is made via a customer definition.
Product definitions have two identifiers, one is the database id used to identify the product within the AA system, this is dynamically assigned. The other identifier is the external_product_id, this identifier is how the product is defined in an external system. This could be a SKU, or salesforce product definition id, or Control Tower Asset Id, a contract identifier, or just a random string.
Products and Customers may be managed through the au-saas.py, manage_tenants.py scripts, or via rest API.
An AA product file is a json representation of the integration. See product files sample product files for examples of what can be contained in product files. The json defines UI representations oF a product, AA licenses which are to be granted, as well as onboarding actions.
Customers
An AA Customer is an association between a Product and a Tenant, and the state of that association, and any metadata which is required for the product. Every SaaS tenant should have at least one customer record associating it with a product.
Customer definitions have two identifiers, one is the database id used to identify the customer within the AA system, this is dynamically assigned. The other identifier is the external_customer_id, this identifier is how the customer is defined in an external system. This could be something like a salesforce customer id. In addition the customer record contains the current state of the relationship (enabled/disabled), and metadata about the product being associated with the tenant. That metadata could be things like external service locations.
Customers and Products may be managed through the au-saas.py, manage_tenants.py scripts, or via rest API.
SaaS Specific AA Scripts
Each of these scripts have cmd line help. To invoke scripts which must be executed from the aucore container:
- local development system:
- Open a shell and cd into the “aucore/AuCore/app” directory
- With the system running (i.e. make dev-up should already be executing in a different shell)
run "make dev-exec-shell" # or "make saas-dev-exec-shell"
run "au-saas-install development.ini"
- kubernetes based system:
kubectl exec -it -c aucore master-aaf-0 -- /bin/bash
Scripts:
-
au-saas-install - Called once and only once during initial setup of a SaaS system, intended audience is development and Managed SasS Admins. Invoked from the aucore-container.
au-saas-install production.ini -
au-saas - Used to manage products, customers, and their associated licenses. Invoked from the aucore container. See the au-saas help for additional details
# show all tenants, products, and customers au-saas production.ini display # compare all tenants with their associated products and update licenses and onboarding actions # this should be run after adding/removing products to a tenant or after changing a product file au-saas production.ini reprocess # Run this to rekey all service accounts au-saas production.ini reprocess-issue-new-tokens # Run this if tenant is associated with a product file containing a time limited trial license and we need to extend the trial au-saas production.ini --product XYZ --tenant_name=SIX extendlicense # development system samples # adding a new product into the system au-saas development.ini add --product=SA-AB804 --topic=reserved --file=aa-trial.json # adding a product to a tenant au-saas development.ini add --product=SA-AB804 --tenantname=SIX --customer=CTAssetIDforSA-AB804-SIX # remove a customer (removes the product from the tenant) au-saas development.ini delete --customer=CTAssetIDforSA-AB810-ONE # after all operations are complete run reprocess to ensure that all tenants are properly updated au-saas development.ini reprocess # create a large number of tenants au-saas development.ini bloat -
onboard_tenant.py - used to call the rest apis to onboard tenants, or add additional products to tenants. Invoked from any system running python, requires TOP admin credentials. Available from the AA samples directory.
# Add the product file to the system python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -f sample-test-service.json -pid sts newproduct # Associate the product with an existing tenant python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -pid sts -cid sts --json addproduct # Verify the product is associated to the tenant python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -tn {tenant_name} --json display # The following command would create a new tenant and associate it with the sample test service product file python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -tn ONBOARDTENANTSCRIPTTEST2 -td "description" -te admin@onboardtenantscripttest.frog.com -tp "1plethora*" -pid sts -cid sts --json newtenant -
bulk_operations.py - allows json files to be submitted to the the service for processing. Available from the AA samples directory.
-
manage_token.py - create tokens used for SCIM and other API access. Invoked from any system running python, requires admin credentials. Available from the AA samples directory.
Product Files
When a product file is associated with a tenant (via a customer record) the results of onboarding and other actions taken will be returned to the caller.
Top level items in a product file
-
force_on_tenant - optional (boolean) True means that this product is automatically associated with every tenant created. Useful for default licensing or global replacement variables (bulkids)
-
description - required, json block containing
- name - (string) natural language name of the product
- nameid - (string) id for localization of the name
- fulldesc - (string) an English description of the product
- fulldescid - (string) id for localization of the description
-
billing - optional, deprecated
-
licenses - optional (json) containing AA specific license information consult with AA engineers on specifics.
-
onboarding_actions - optional (json) block see Onboarding Actions in product files
-
bulkids - optional (json) block of key value pairs which are global replacement variables for bulk operations using the rest api, and are available during onboarding operations as replacement variables.
Sample product definition files:
- aa-base.json SA-AB807 - support for all authentication methods, the billing dimension is per user per month. Used when a customer buys AA.
{
"licenses": [{"restricts": [{"type": "limited", "methods": {"*": {}}}]}],
"billing": {"dimensions": ["user_month"]},
"description": {"name": "AA Base", "nameid": "SA-AB807", "fulldesc": "Adaptive Authentication Base Active User Monthly Subscription SaaS", "fulldescid": "SA-AB807"},
"onboarding_actions":
{
"create_scim_repos": [
{"name": "IAMSERVICES"}
]
}
}
- ig-aa-addon.json Optional add-on product that must be added when customer purchases IG SaaS. No billing, only allows the methods allowed in aa-limited.
{
"description": {name": "IG-AA", "nameid": "IG-AA-Integration", "fulldesc": "Identity Governance Integration with Advanced Authentication", "fulldescid": "IG-AA-Integration"},
"onboarding_actions":
{
"issue_token": true,
"create_scim_repos": [
{"name": "IGBOOTSTRAPS", "scim_repo_create_config": {"user_repository_alias": "IGBOOTSTRAPS"}},
{"name": "IAMSERVICES"}
]
}
}
- aa-limited.json SA-AB805 - an AA instance with support for limited authentication methods (email otp, emergency password, HOTP, ldap password, password, radius, SMS otp and TOTP).
{
"licenses": [{"restricts": [{"type": "limited", "methods": {"EMAIL_OTP:1": {}, "EMERG_PASSWORD:1": {}, "HOTP:1": {}, "LDAP_PASSWORD:1": {}, "PASSWORD:1": {}, "RADIUS:1": {}, "SMS_OTP:1": {}, "TOTP:1": {}, "SAML_SP:1": {}}}]}],
"billing": {"dimensions": ["user_month"]},
"description": {"name": "AA Limited", "nameid": "SA-AB805", "fulldesc": "Adaptive Authentication Limited Active User Entitled Monthly Subscription SaaS", "fulldescid": "SA-AB805"},
"onboarding_actions":
{
"create_scim_repos": [
{"name": "IAMSERVICES"}
]
}
}
- aa-trial.json SA-AB804 - an AA instance with full AA support including risk. Limited to 50 users for one month.
{
"licenses": [{"days": 31, "restricts": [{"type": "risk_service"}, {"type": "trial", "users": 50}]}],
"billing": {"dimensions": ["user_month"]},
"description": {"name": "AA Trial", "nameid": "SA-AB804", "fulldesc": "Adaptive Authentication Trial Active User 1-Month Subscription SaaS", "fulldescid": "SA-AB804"},
"onboarding_actions":
{
"create_scim_repos": [
{"name": "IAMSERVICES"}
]
}
}
- aa-risk.json SA-AB888 - a Risk based Adaptive AA instance with support for all authentication methods, the billing dimension is per user per month. Used when a customer buys Adaptive AA. Requires aa-client-usage and aa-data-usage be installed in tandem.
{
"licenses": [{"restricts": [{"type": "limited", "methods": {"EMAIL_OTP:1": {}, "EMERG_PASSWORD:1": {}, "HOTP:1": {}, "LDAP_PASSWORD:1": {}, "PASSWORD:1": {}, "RADIUS:1": {}, "SMS_OTP:1": {}, "TOTP:1": {}, "SAML_SP:1": {}}}]}],
"billing": {"dimensions": ["user_month"]},
"description": {"name": "AA Adaptive", "nameid": "SA-AB808", "fulldesc": "Adaptive Authentication Adaptive Active User Monthly Subscription SaaS", "fulldescid": "SA-AB808"}
}
Onboarding Actions in product files
In the json product file there is a section for onboarding actions to be taken when the tenant is created. Testing the bulk section of the product file can be done using the bulk operations rest API
"onboarding_actions": {
"issue_token": true,
"create_scim_repos": [
{
"name": "SaaSAdmins",
"scim_repo_create_config": {
"user_repository_alias": "admin"
},
"token_ttl": "1h",
"bulk": {
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:BulkRequest"
],
"fullResponses": true,
"failOnErrors": 3,
"Operations": [
{
"method": "GET",
"bulkId": "get-app-id",
"path": "/rest/admin/bulk"
},
{
"method": "POST",
"path": "/Users",
"data": {
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:User",
"urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
"urn:scim:schemas:extension:custom:1.0"
],
"externalId": "aa-bulkId:get-app-id",
"userName": "aa",
"emails": [
{
"value": "aa@example.com",
"type": "work",
"primary": true
}
],
"roles": [
{
"display": "SERVICE_ACCOUNTS"
},
{
"display": "TENANT_ADMINS"
}
],
"urn:scim:schemas:extension:custom:1.0": {
"openid_scopes": {
"openid": false,
"mandatory": false,
"require_owner_permission": false,
"name": "aa:AdminUI",
"title": "Admin UI Allowed"
}
}
}
},
{
"method": "GET",
"path": "/Users?filter=externalId eq \"701984\"",
"bulkId": "get-aa-service-id"
},
{
"method": "PATCH",
"path": "/Users/bulkId:get-aa-service-id?attributes=password",
"data": {
"schemas": [
"urn:ietf:params:scim:schemas:core:2.0:PatchOp"
],
"Operations": [
{
"op": "replace",
"path": "password",
"value": ""
}
]
}
}
]
}
}
],
"bulk": {
"fullResponses": true,
"failOnErrors": 3,
"Operations": [
{
"method": "GET",
"bulkId": "get-email-chain",
"path": "/rest/admin/api/chains"
},
{
"method": "POST",
"bulkId": "create-email-chain",
"path": "/rest/admin/api/chains",
"data": {
"name": "simple name",
"is_enabled": true,
"methods": [
"EMAIL_OTP:1"
],
"roles": [
{
"name": "ALL USERS",
"idx": 0
}
],
"repos": [
{
"name": "LOCAL",
"idx": 0
}
]
}
}
]
}
-
Also see the bulk operations section of this document for further samples of potential bulk operations.
-
Warning, product files may be run both during onboarding and if the COE runs the admin script au-saas with the reprocess option. If reprocessing product files any bulk operations should assume the objects may already exist and will get the 409 conflict error.
-
issue_token results in a bearer token being issued which allows for public APIs to be called, the default validity period is 7 days, this can be changed by setting “token_ttl”: “1h”. Valid values for token_ttl are a number and a unit for example: 24days, 1hour, 60seconds see pytimeparse2 for additional examples. The issued bearer token has tenant admin privileges, best practices should be followed with securing the token.
-
scim_repo_create_name results in a scim repo of the specified name to be created, the onboarding response will contain a bearer token valid for 1 year that allows all operations on the SCIM repo.
-
scim_repo_create_config any configuration options valid on a SCIM repo. Repo aliases may be set using the attribute ‘user_repository_alias’.
-
create_scim_repos - allows multiple scim repos to be created instead of just one, this is the preferred format, the ‘scim_repo_create_name’ will be phased out in the future. Each created repo will be issued a token for repo operations. The operations under the bulk tag are assumed to be SCIM bulk operations as documented in rfc 7644
-
Creating a user with a blank password “” results in a generated password being assigned to the user and returned to the caller.
-
Globally defined well known bulkids. AA knows and populates the following bulkids by default:
- aa_tenant_name - well known bulkId contains the tenant name such as TOP
- aa_tenant_base - in SaaS systems this will be the base domain to which the tenant name is prepended to get the per tenant hostname. This will not be populated in non-SaaS systems
- aa_tenant_domain the url specific to the tenant for example: top.cyberresdev.com (lowercase) It will not always be bulkId:aa_tenant_name.bulkId:aa_tenant_base it may be the domain used in federating with external SAML IDPs.
-
During onboarding operations bulkids are resolved in the following order 1) well known AA bulkids such as ‘aa_tenant_name’, ‘aa_tenant_base’, ‘aa_tenant_domain’ 2) from the bulkids associated with a specific customer config, 3) from templates on every product associated with the tenant 4) from templates on bulkids from the product file (global values this is the only product file that must be created per install)
-
bulkid templates are any bulkid named with the suffix
_template. During the building of the bulkid list for resolution only bulkids with_templatewill be used from customer, and product configs.
Changes to products already associated with a tenant
There are two approaches to updating products already associated with a tenant:
- In place upgrade of the product json. Requires access to the containers to run the au-saas script.
Steps:
- Update the existing product json
au-saas production.ini update --product {product id} --file {updated product json file}
- Reprocess all product definitions, from the console of the aucore container
au-saas production.ini reprocess
- Associate a new product with existing tenants. May be done via SaaS API or via a combination of au-saas and onboard-tenant. This method allows for incremental updates, and full rollback.
Steps:
- Create a new product with the new product.json
python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -f sample-test-service.json -pid new_sts newproduct - List all tenants associated with the old product
- Create a new product with the new product.json
-
Add new product to all tenants who had the old product
-
Remove the old product association from all tenants
-
Remove the old product definition
python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -f sample-test-service.json -pid sts newproduct
-
Infrastructure as Code
In the onboarding_actions section a section labeled [bulk] may contain a set of rest calls to setup AA for the application may be included. See the sample above for possible uses. Alternatively scripts such as bulk_operations.py may call the AA bulk operations. Currently the bulk operations have been tested using the AA Public API as well as chains, events, policy, and methods from the AA Admin API. The structure of the bulk operations follows the same general rules as SCIM bulk operations.
Warning, product files may be run both during onboarding and if the COE runs the admin script ‘au-saas’ with the reprocess option. If reprocessing product files any bulk operations should assume the objects may already exist and will get the 409 conflict error. In the example below the bulk operations are structured such that proper result is achieved regardless of the prior state of the object. In this example the proper result is that the object exists and has had it’s password set.
{
"fullRequests": false,
"fullResponses": true,
"failOnErrors": 1,
"Operations": [
{"method": "GET", "bulkId": "get-app-id", "path": "/rest/admin/bulk"},
{"method": "POST", "path": "Users",
"data": {
"schemas": ["urn:ietf:params:scim:schemas:core:2.0:User", "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User",
"urn:scim:schemas:extension:aa:1.0"],
"externalId": "aa-bulkId:get-app-id",
"userName": "aa",
"emails": [{"value": "aa-service@bulkId:aa_tenant_domain", "type": "work", "primary": True}],
"roles": [{"display": "SERVICE_ACCOUNTS"}],
"urn:scim:schemas:extension:aa:1.0": {
"openid_scopes": [ {"openid": False, "mandatory": False, "require_owner_permission": False, "name": "aa:AdminUI", "title": "Admin UI Allowed", "attributes": [
{"localName": "tenantname", "clientName": "tenantname"},
{"localName": "mobile", "clientName": "user_mobile_phone"},
{"localName": "userFirstName", "clientName": "user_first_name"},
{"localName": "userLastName", "clientName": "user_last_name"},
{"localName": "username", "clientName": "user_name"},
{"localName": "userRepository", "clientName": "user_repository_alias"},
{"localName": "mail", "clientName": "user_email"}] } ],
"oauth2_aud_base": "https://bulkId:aa_tenant_domain\n"https://bulkId:cb_tenant_domain"
}
}
},
{"method": "GET", "path": "Users?filter=emails[value] eq \"aa-service@bulkId:tenant_aa_domain\"]", "bulkId": "get-aa-service-id"},
{"method": "PATCH", "path": "Users/bulkId:get-aa-service-id", "bulkId": "patch-aa-service-pwd",
"data": {"schemas": ["urn:ietf:params:scim:schemas:core:2.0:PatchOp"], "Operations": [{"op": "replace", "path": "password", "value": ""}]
}
}
]
}
Instead of using explicit URIs in the example above it would be best practices to use bulkId:somevar and then add somevar to the metadata sent to the bulk operation, or somevar_template to metadata stored on the customer, or include somevar_template in the product definition.
A practical example. CBA and ILM both create service accounts and intend to communicate with each other, both require that incoming tokens have an audience set correctly, and both create their service account through their respective product files which are installation agnostic. So how can the ILM service account definition specify that the CBA should be one of it’s resources/audiences? If there is a well known convention for the location of services then the actual service account definitions can use the convention to list audiences that will be specified at a later time.
The conventions can be defined in one of two ways
- In series of
_templatesstored in a single product file which is associated with all tenants by default. This product file would be landing zone dependent, and could be altered if any services shift from shared multitenancy to per-tenant names.
{
"description": {"name": "IAM Service configuration", "nameid": "IAM-Service-Config"},
"force_on_tenant": true,
"bulkids": {
"cba_domain_template": "cba.frog.com",
"ilm_tenant_domain_template": "bulkId:aa_tenant_name.ilm.bulkId:aa_tenant_base",
"pwm_domain_template": "password.bulkId:aa_tenant_base",
"iga_tenant_domain_template": "bulkId:aa_tenant_name.iga.bulkId:aa_tenant_base"
}
}
- When the product file is registered the caller may inject the proposed template into the agnostic product prior to registration with AA. In the example below the CBA product file is injected with the landing zone specific rule for
cat aucore/products/cba.json | jq '. + {"bulkids": {"cba_domain_template": "cba.frog.com"}}'
Assuming the above template has been registered with AA using one of the methods above, then services may use any of the templates listed above by including the name of the bulkId (excluding the word template)
"oauth2_aud_base": "https://bulkId:cba_domain\nhttps://bulkId:ilm_tenant_domain\nhttps://bulkId:iga_tenant_domain_template"
If oauth2_aud_base includes a bulkId which cannot be resolved then AA removes that audience from the list before configuring OSP.
Per Tenant Hostname
This is a simple assignment of each tenant to a subdomain under the primary domain where aa is running. For example, assuming that we own the domain name cyberresprod.com we could have top.cyberresprod.com represent the top tenant, each tenant added would be assigned a name (tenant_name).cyberresprod.com. Tenants would need to use that name to access both their admin pages and for regular client access such as enrollment.
Per Tenant Hostname Assumptions
Assumes that a wildcard cert is in use, for the example above *.cyberresprod.com Assumes SRE has easy access to create DNS names for each tenant and would incorporate that in their onboarding flow. Allows tenant discovery to be based in the incoming hostname, thus eliminating the need for the user to know their tenant name. Also allows us to have one AA instance which has tenants with overlapping user or email names.
Per Tenant Hostname Testing / Deployment Instructions
-
load balancer in front of AA must be set with wildcard cert on the tenant_base.
-
load balancer must accept all dns names of the form *.tenant_base.
-
The dns system used by the installed aa must be able to resolve all tenant_name.tenant_base names.
-
Under Policies/Public URL(load balancers) the default and the tenant_base must be set correctly.
-
Fresh install
- Verify that all auth urls and an issuers are tenant_name.base_tenant_domain
- verify cb install and radius scripts get the correct domain name
- verify that install flow returns the correct domain name
-
Upgrade
- Existing tenants should still have the old common webauth url as the issuer and public url
- New tenants should get the new tenant_name.base_tenant_domain
- Existing tenants will get the tenant_name.base_tenant_domain added to their logon domains by a background celery task, this task will also handle injecting tenant.base_name if the base name changes. Note the old tenant.base_name is not removed.
- Existing tenants who don’t have a webauth url will need to set it properly. Changing the webauth url will require any federations be updated.
- What needs to happen for IG to get the new domain name?
Advanced Authentication Hosted SaaS API doc
The rest apis in this section are intended only for use when Advanced Authentication has been installed as a SaaS Product.
Authentication
Acceptable authentication to the rest apis is either a login_session_id passed on each call or a bearer token passed in the http header
as Authorization: Bearer {token}.
Tenant Onboarding ¶
Advanced Authentication Onboarding Tenants
This is the process of creating a customer instance, and associating that instance with one or more products. The assumption in the IAM SaaS is that Advanced Authentication provides the authentication for all services, therefore AA will be the first product installed.
Onboarding Assumptions
-
System has been setup for SaaS and multi tenant mode.
-
The AA system has been configured with SaaS products. An AA product is a json representation of a purchasable block of functionality. The json defines UI representations, AA licenses which are to be granted, and optionally information about policies. See create product rest api for details. Products may also be installed via the au-saas script.
-
Authorization for onboarding is only available as a TOP superadmin user.
Onboarding a new Tenant via the AA admin UI for internal and trial customers
This is primarily for testing, it does not allow for adding additional products to existing tenants. On tenant create a single product may be associated with a tenant. The customerid is not passed random
Onboarding additional products to an existing tenant
- Call Onboarding
Onboarding via scripts or lambda functions - Used by Open Text Center of Excellence
This is a UI less onboarding of new tenants or association of new products with the existing tenant.
Onboarding Authentication and Authorization
Creating new tenants and removal of any product associations requires TOP superadmin privileges. Tenant admins may add additional products to their tenant.
The script manage_token.py may be used to obtain tokens for use with this script or if only user/password is required then that may be used in this script.
Script Examples
# add new products to the system
python3 onboard_tenant.py --host https://localhost --user admin --password admin create -pid 1 -ch None -f ../app/aucore/products/aa-limited.json
python3 onboard_tenant.py --host https://localhost --user admin --password admin create -pid 2 -ch None -f ../app/aucore/products/aa-limited-overage.json
python3 onboard_tenant.py --host https://localhost --user admin --password admin create -pid 3 -ch None -f ../app/aucore/products/ig-aa-addon.json
# Add the product file to the system
python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -f sample-test-service.json -pid sts newproduct
# Associate the product with an existing tenant
python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -pid sts -cid sts --json addcustomer
# Disassociate product with a tenant (removes customer record)
python3 {} --host 127.0.0.1 --user admin --password "1plethora*" -pid sts -cid sts -json removecustomer
# Remove a product from the system (all customer records associated with the product must be removed first)
python3 {} --host 127.0.0.1 --user admin --password "1plethora*" -f pwm.json -pid pwm removeproduct
# Verify the product is associated to the tenant
python3 onboard_tenant.py --host 127.0.0.1 --user admin --password "1plethora*" -tn {tenant_name} --json display
# create a new tenant
python3 onboard_tenant.py --host https://localhost --user admin --password admin create -pids 1,2,3 -cids c1,c2,c3 -tn FROGGY -td "Froggy Tenant" -tp admin -te=fakeadmin@froggy.com
( { 'results': [ { 'admin': { 'id': 'ddb37d7d4cf43586abaa911e9a44fb80',
'last_fail_at': None,
'loginame': 'fakeadmin@froggy.com',
'obj_id': '5de91d34ddd811eba5e00242ac110004',
'repo_id': '5dde8414ddd811eba5e00242ac110004',
'repo_name': 'LOCAL',
'user_name': 'LOCAL\\fakeadmin@froggy.com'},
'chains': [ {'id': '5dc63f30ddd811eba5e00242ac110004', 'methods': ['LDAP_PASSWORD:1'], 'name': 'LDAP Password Only'},
{'id': '5dc418f4ddd811eba5e00242ac110004', 'methods': ['PASSWORD:1'], 'name': 'Password Only'}],
'customer': { 'billing': {'dimensions': ['user_month'], 'history': [{'user_month': []}]},
'external_customer_id': 'c1',
'external_product_id': '1',
'id': '5de10b1cddd811eba5e00242ac110004',
'product_id': 'b3ebcb3addb211eb98800242ac110004',
'state': 'subscribe',
'tenant_id': '5daafd56ddd811eba5e00242ac110004',
'tenant_name': 'FROGGY'},
'domains': ['froggy.com'],
'product': { 'data': { 'billing': {'dimensions': ['user_month']},
'description': { 'fulldesc': 'Adaptive Authentication Limited Active User Entitled Monthly Subscription SaaS',
'fulldescid': 'SA-AB805',
'name': 'AA Limited',
'nameid': 'SA-AB805'},
'licenses': [ { 'restricts': [ { 'methods': { 'EMAIL_OTP:1': {},
'EMERG_PASSWORD:1': {},
'HOTP:1': {},
'LDAP_PASSWORD:1': {},
'PASSWORD:1': {},
'RADIUS:1': {},
'SMS_OTP:1': {},
'TOTP:1': {}},
'type': 'limited'}]}]},
'external_product_id': '1',
'id': 'b3ebcb3addb211eb98800242ac110004',
'notification_channel': 'None'},
'tenant': { 'desc': 'Froggy Tenant',
'disabled': False,
'expired_warning': False,
'id': '5daafd56ddd811eba5e00242ac110004',
'license_min': '9999-12-31T00:00:00.0',
'name': 'FROGGY',
'repo_count': 1}},
{ 'admin': { 'id': '79450d085a98148221e7b1a03468397a',
'last_fail_at': None,
'loginame': 'ADMIN',
'obj_id': '4ece8bf2db5011eb89260242ac110004',
'repo_id': '4ecc8690db5011eb89260242ac110004',
'repo_name': 'LOCAL',
'user_name': 'LOCAL\\ADMIN'},
'chains': [ {'id': '5dc63f30ddd811eba5e00242ac110004', 'methods': ['LDAP_PASSWORD:1'], 'name': 'LDAP Password Only'},
{'id': '5dc418f4ddd811eba5e00242ac110004', 'methods': ['PASSWORD:1'], 'name': 'Password Only'}],
'customer': { 'billing': {'dimensions': ['user_month'], 'history': [{'user_month': []}]},
'external_customer_id': 'c2',
'external_product_id': '2',
'id': '5e5acf42ddd811eba5e00242ac110004',
'product_id': 'b41f0392ddb211eb98800242ac110004',
'state': 'subscribe',
'tenant_id': '5daafd56ddd811eba5e00242ac110004',
'tenant_name': 'FROGGY'},
'domains': ['froggy.com'],
'product': { 'data': { 'description': { 'fulldesc': 'Adaptive Authentication Limited Active User Overage Monthly Subscription SaaS',
'fulldescid': 'SA-AB806',
'name': 'AA Limited Overage',
'nameid': 'SA-AB806'}},
'external_product_id': '2',
'id': 'b41f0392ddb211eb98800242ac110004',
'notification_channel': 'None'},
'tenant': { 'desc': 'Froggy Tenant',
'disabled': False,
'expired_warning': False,
'id': '5daafd56ddd811eba5e00242ac110004',
'license_min': '9999-12-31T00:00:00.0',
'name': 'FROGGY',
'repo_count': 1}},
{ 'admin': { 'id': '79450d085a98148221e7b1a03468397a',
'last_fail_at': None,
'loginame': 'ADMIN',
'obj_id': '4ece8bf2db5011eb89260242ac110004',
'repo_id': '4ecc8690db5011eb89260242ac110004',
'repo_name': 'LOCAL',
'user_name': 'LOCAL\\ADMIN'},
'bearer_token': 'eyJhbGciOiJkaXIiLCJhdWQiOiJ0cyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJpc3MiOiJ0cyIsInRlbiI6IjVkYWFmZDU2ZGRkODExZWJhNWUwMDI0MmFjMTEwMDA0In0..XqkAl0siA_70szbBKTFkGA.WxDs-b3sqekZ328UdgcHQGqEQ6-2xCuytcR4o21IL3oGnBkt7NfNifTD1AL1Q-cYSdp8b_Rb_WIDIay_j9PvBYaFnf0Gf99tkTwG9BkouYOiMGNeKJ3wgv-5TH5TLRfm6DsVRkdIUdSRFuREtAkldlmw-zNZXTgknLhxutO4xU3t1TVcwOCYfqs2qNimHPTH9eAOq-QZlwe0XivwGPeqxg2oE1_d_W7QUgIT5kXleBNXVV9DxHrG19eINDzaz0MRgkn6zgOV1gx2kBS1F1ScLoheqzOg1ooNaBctEe8-dOfaE9R6H6bCDoSI4pZ0hO2yUTQd8lYydoLSt7dBiq0VXC-xO5eUDL-xQ3aY42gJDsXsBFGaNnomnc4VFQMtSB2t.TIxPCYHhGv_hKC5iFurTxA',
'chains': [ {'id': '5dc63f30ddd811eba5e00242ac110004', 'methods': ['LDAP_PASSWORD:1'], 'name': 'LDAP Password Only'},
{'id': '5dc418f4ddd811eba5e00242ac110004', 'methods': ['PASSWORD:1'], 'name': 'Password Only'}],
'customer': { 'billing': {'dimensions': ['user_month'], 'history': [{'user_month': []}]},
'external_customer_id': 'c3',
'external_product_id': '3',
'id': '5eacc84cddd811eba5e00242ac110004',
'product_id': 'b453f462ddb211eb98800242ac110004',
'state': 'subscribe',
'tenant_id': '5daafd56ddd811eba5e00242ac110004',
'tenant_name': 'FROGGY'},
'domains': ['froggy.com'],
'product': { 'data': { 'description': { 'fulldesc': 'Identitiy Governance Integration with Advanced Authentication',
'fulldescid': 'IG-AA-Integration',
'name': 'IG-AA',
'nameid': 'IG-AA-Integration'},
'onboarding_actions': {'issue_token': True, 'scim_repo_create_name': 'ig_bootstraping'}},
'external_product_id': '3',
'id': 'b453f462ddb211eb98800242ac110004',
'notification_channel': 'None'},
'scim_repo': { 'bearer_token': 'eyJhbGciOiJkaXIiLCJhdWQiOiJ0cyIsImVuYyI6IkExMjhDQkMtSFMyNTYiLCJpc3MiOiJ0cyIsInRlbiI6IjVkYWFmZDU2ZGRkODExZWJhNWUwMDI0MmFjMTEwMDA0In0..pqXpckYrIrJJ7zbBzKgs8w.TCfEBoPeH0peCUrI0lUDp8lfCe-BbtG9M_feVyYdEgZ9qPsRNXjrT24xc0nK6NHSpqjaAuZjTAYF6Kd6xEsZM_19LYr_v2hjWxkCwRpJ3KWjDTlEFZo7e_nGnLG9QaQ8ZX3ByRkFYJjL4WaY0lINhff_JXw8TbxcXlUeIJpxz00LBIs2prxBpAaKwW3_j-vqhaLPs5bAjbfZ7Ug61pMdUAnKqGbYnhOnk2jkV1iMdt7_8foJ61olzNV4IIeGM1pBCWjkUM5zEUaCFnLyPmEch_tlEGxa5K3RIcNHO_XqAI-KJBRXPgFmmZ6AT-F4n7tJ2-lSUSsN4o6y-uaYdGR0ccEXIECjENDjiquN-zD9_Q9Hei94YRrMtqK013yF_2y4wORO-p_jZBJCRKZmvzHWPJCXIj_OfBOweL61vhy5v-Y.xPj5oFI6wVcJlfjDHq3x8w',
'name': 'ig_bootstraping'},
'tenant': { 'desc': 'Froggy Tenant',
'disabled': False,
'expired_warning': False,
'id': '5daafd56ddd811eba5e00242ac110004',
'license_min': '9999-12-31T00:00:00.0',
'name': 'FROGGY',
'repo_count': 1}}]},)
AA show all customers and products associated with a tenant: ¶
Headers
Content-Type: application/jsonBody
{
'login_session_id': 'LRvql8GD946V7ryN8fesWBLhN1I7dpEe'
}Headers
Content-Type: application/jsonBody
{}AA show all customers and products associated with a tenant:GET/api/v1/saastenant
AA new tenant onboarding: ¶
Headers
Content-Type: application/jsonBody
{
'login_session_id': 'LRvql8GD946V7ryN8fesWBLhN1I7dpEe',
'tenant_name': "Tenant43',
'tenant_desc': "Tenant 43 description',
'tenant_admin_password': '1234567890Ab',
'tenant_admin_email': 'admin@frog.com',
'tenant_admin_mobile': '+18018615555',
'associations': [{'external_product_id': 'original', 'external_customer_id': 'internal:original:1', 'config': {'bulkids': {'oauth2_redir_uris': 'https://example.com'}}]
}Headers
Content-Type: application/jsonBody
{
'results': [
{
'admin':
{
'id': '633196a3a49269609003fe3ef2270c9a',
'last_fail_at': None,
'loginame': 'froggy@1.frog.com',
'obj_id': 'e5308514de7b11ea87b10242ac110004',
'repo_id': 'e517bc5ade7b11ea87b10242ac110004',
'repo_name': 'LOCAL',
'user_name': 'LOCAL\froggy@1.frog.com'
},
'customer':
{
'external_customer_id': '1',
'external_product_id': 'trial',
'id': 'e517f058de7b11ea87b10242ac110004',
'product_id': '81d4a014de4d11eab9570242ac110004',
'state': 'subscribe',
'tenant_id': 'e502a1b2de7b11ea87b10242ac110004',
'tenant_name': '1FROG'
},
'domains':
['1.frog.com'],
'product':
{
'data':
{
'description':
{
'fulldesc': 'Allows total of 50 users to access all Advanced Authentication functionality for 45 days',
'fulldescid': 'trial-fulldesc-id',
'name': 'Trial AA License (50 users, 45 days)',
'nameid': 'trial-name-id'
},
'licenses':
[
{
'days': 45,
'restricts':
[
{
'type': 'risk_service'
},
{
'type': 'trial',
'users': 50
}
]
}
],
'external_product_id': 'trial',
'id': '81d4a014de4d11eab9570242ac110004',
'notification_channel': 'rad'
},
'tenant':
{
'desc': 'test desc',
'expired_warning': False,
'id': 'e502a1b2de7b11ea87b10242ac110004',
'license_min': '9999-12-31T00:00:00.0',
'name': '1frog',
'repo_count': 1
}
}
]
}AA new tenant onboarding:POST/api/v1/saastenant
Create a new tenant, create admin user, associate products, run any policy/license updates, and perform onboarding actions.
SaaS Management ¶
Return a list of all currently configured SaaS Products: ¶
Headers
Content-Type: application/jsonBody
{
'login_session_id': 'LRvql8GD946V7ryN8fesWBLhN1I7dpEe'
}Headers
Content-Type: application/jsonBody
{
'products'
[
{
'data':
{
'description':
{
'fulldesc': 'Allows total of 50 users to access all Advanced Authentication functionality for 45 days',
'fulldescid': 'trial-fulldesc-id',
'name': 'Trial AA License (50 users, 45 days)',
'nameid': 'trial-name-id'
},
'licenses':
[
{
'days': 45,
'restricts':
[
{
'type': 'risk_service'
},
{
'type': 'trial',
'users': 50
}
]
}
],
'external_product_id': 'trial',
'id': '81d4a014de4d11eab9570242ac110004',
'notification_channel': 'rad'
}
]
}Return a list of all currently configured SaaS Products:POST/api/v1/saasproductlist
Update a SaaS Product definition: ¶
Headers
Content-Type: application/jsonBody
{
'login_session_id': 'LRvql8GD946V7ryN8fesWBLhN1I7dpEe',
'external_product_id': 'trial-changed',
'notification_channel': 'rad-changed'
}Headers
Content-Type: application/jsonBody
{
'id': '123456789999',
'external_product_id': 'trial-changed',
'notification_channel': 'rad-changed'
'data':
{
'description':
{
'fulldesc': 'Allows total of 50 users to access all Advanced Authentication functionality for 45 days',
'fulldescid': 'trial-fulldesc-id',
'name': 'Trial AA License (50 users, 45 days)',
'nameid': 'trial-name-id'
},
'licenses':
[
{
'days': 45,
'restricts':
[
{
'type': 'risk_service'
},
{
'type': 'trial',
'users': 50
}
]
}
]
}
}Update a SaaS Product definition:PUT/api/v1/saasproduct/{product_id}
Pass in the fields to be updated in the product definition, the updated product be returned.
- product_id
string(required) Example: 1234567890
Delete a Product definition: ¶
Headers
Content-Type: application/jsonBody
nullDelete a Product definition:DELETE/api/v1/saasproduct/{product_id}?login_session_id={login_session_id}
- product_id
string(required) Example: 1234567890- login_session_id
string(required) Example: LRvql8GD946V7ryN8fesWBLhN1I7dpEeID of the login session
Return a list of all currently configured SaaS Customers: ¶
Headers
Content-Type: application/jsonBody
{
'login_session_id': 'LRvql8GD946V7ryN8fesWBLhN1I7dpEe'
}Headers
Content-Type: application/jsonBody
{
'customers'
[
{
'external_customer_id': '1',
'external_product_id': 'trial',
'id': 'e517f058de7b11ea87b10242ac110004',
'product_id': '81d4a014de4d11eab9570242ac110004',
'state': 'subscribe',
'tenant_id': 'e502a1b2de7b11ea87b10242ac110004',
'tenant_name': '1FROG'
}
]
}Return a list of all currently configured SaaS Customers:POST/api/v1/saascustomerlist
Update a SaaS Customer: ¶
Headers
Content-Type: application/jsonBody
{
'login_session_id': 'LRvql8GD946V7ryN8fesWBLhN1I7dpEe',
'external_product_id': 'trial-changed',
'external_customer_id': 'rad-changed',
'state': 'disabled',
'config': {'bulkids': {'bulkid1': 'bulkid1-value'}}
}Headers
Content-Type: application/jsonBody
{
'external_customer_id': '1',
'external_product_id': 'trial',
'id': 'e517f058de7b11ea87b10242ac110004',
'product_id': '81d4a014de4d11eab9570242ac110004',
'state': 'subscribe',
'tenant_id': 'e502a1b2de7b11ea87b10242ac110004',
'tenant_name': '1FROG'
}Update a SaaS Customer:PUT/api/v1/saascustomer/{customer_id}
Pass in the fields to be updated, the updated customer will be returned. Either external_product_id or state must be passed. Valid states: ‘subscribe’, ‘enabled’, ‘unsubscribe-pending’, ‘disabled’ ‘config’ is optional, see the AA SaaS API documentation for discursion of bulkid_templates and bulkid resolution. To remove a customer association set the state to unsubscribe-pending, not disabled. This allows for final processing of the any reports or billing information.
- customer_id
string(required) Example: 1234567890
Delete a customer definition: ¶
Headers
Content-Type: application/jsonHeaders
Content-Type: application/jsonBody
nullDelete a customer definition:DELETE/api/v1/saascustomer/{customer_id}?login_session_id={login_session_id}
- customer_id
string(required) Example: 1234567890- login_session_id
string(required) Example: LRvql8GD946V7ryN8fesWBLhN1I7dpEeID of the login session
Configure required Cloudbridge data: ¶
Headers
Content-Type: application/jsonBody
{
"login_session_id": "LRvql8GD946V7ryN8fesWBLhN1I7dpEe",
"docker_image_download": "",
"docker_image_name": "",
"agents":
[
{"agent file as delivered from the COE"}
]
}Headers
Content-Type: application/jsonBody
nullConfigure required Cloudbridge data:PUT/api/v1/saascloudbridge/{tenant_id}
- tenant_id
string(required) Example: 23456788Tenant name or ID
Get CB configuration status: ¶
Headers
Content-Type: application/jsonBody
{
"repos": [
{
"repo_id": "cd3a051cd5c711eca97e0242ac110002",
"ok": false,
"errors": [],
"is_shared_cbc": true
}
]
}Get CB configuration status:GET/api/v1/saascloudbridge/{tenant_id}/configuration
- tenant_id
string(required) Example: 23456788Tenant name or ID
Run CB configuration repo check: ¶
Headers
Content-Type: application/jsonBody
{
"errors": []
}Run CB configuration repo check:GET/api/v1/saascloudbridge/{tenant_id}/repo/{repo_id}/configuration
- tenant_id
string(required) Example: 23456788Tenant name or ID
- repo_id
string(required) Example: 23456788Repo ID
Force CB configuration: ¶
Headers
Content-Type: application/jsonBody
{
"errors": []
}Force CB configuration:POST/api/v1/saascloudbridge/{tenant_id}/repo/{repo_id}/configuration
- tenant_id
string(required) Example: 23456788Tenant name or ID
- repo_id
string(required) Example: 23456788Repo ID
Tenant domain Management ¶
Read and update logon domains associated with this tenant
Register logon domains for the current tenant: ¶
Headers
Content-Type: application/jsonBody
{
"login_session_id": "B3XBHzwAHuPfHwMHfSjf3eVdV3glCa0o",
"domains": [
{
"name": "test.com"
},
{
"name": "example.com"
}
]
}Headers
Content-Type: application/jsonBody
{
"domains": [
{
"name": "foo.example.com"
},
{
"name": "bar.example.com"
}
]
}Register logon domains for the current tenant:PUT/api/v1/logondomains
Replaces any existing logon domains with the passed domains
Logon domains lookup: ¶
Headers
Content-Type: application/jsonBody
{
"login_session_id": "JHAHdZiRKdaYcPhQUHcPYgYSElFcMBVX"
}Headers
Content-Type: application/jsonBody
{
"domains": [
{
"name": "foo.example.com"
},
{
"name": "bar.example.com"
}
]
}Logon domains lookup:POST/api/v1/logondomains/get
Reads any existing logon domains
Generated by aglio on 29 Oct 2025