From 71987ae60d1670d7867ce846e989389a0004e287 Mon Sep 17 00:00:00 2001 From: Kyaw Myo Thant Date: Tue, 10 Dec 2024 17:41:34 +0900 Subject: [PATCH] Add tutorial to test external oauth2 server This patch adds script to start Keycloak authorization server as a docker container for testing external oauth2 server authentication and a guide of how to use that script in "Using External OAuth 2.0 Authorization Server for Tacker APIs" documentation. And the content of the documentation is reconfirmed with 2024.2 release of Tacker. Change-Id: Id10343da43e121c52227f6c18d0b17af88c72c62 --- .../admin/external_oauth2_usage_guide.rst | 1064 +++--- doc/tools/ext_oauth2_server/base_realm.json | 2942 +++++++++++++++++ doc/tools/ext_oauth2_server/gen_keycloak.sh | 595 ++++ 3 files changed, 4176 insertions(+), 425 deletions(-) create mode 100644 doc/tools/ext_oauth2_server/base_realm.json create mode 100644 doc/tools/ext_oauth2_server/gen_keycloak.sh diff --git a/doc/source/admin/external_oauth2_usage_guide.rst b/doc/source/admin/external_oauth2_usage_guide.rst index 72cd245b5..7c13efa33 100644 --- a/doc/source/admin/external_oauth2_usage_guide.rst +++ b/doc/source/admin/external_oauth2_usage_guide.rst @@ -5,7 +5,7 @@ Using External OAuth 2.0 Authorization Server for Tacker APIs .. note:: The content of this document has been confirmed to work using - Tacker 2024.1 Caracal and Keycloak 25.0.4. + Tacker 2024.2 Dalmatian and Keycloak 26.0.2. Overview @@ -32,12 +32,246 @@ example, the `Keycloak`_ server is used as the external OAuth 2.0 authorization server. The ``$keycloak_host_name`` is the domain name used by the `Keycloak`_ server, and the domain name used by the Tacker server is ``$tacker_host_name``. +Setup External Authorization Server +----------------------------------- + +In this guide, Keycloak server will be configured and started as a docker +container by running the script. But the Keycloak server prepared in other way +can be used if user attributes mapper is setup properly. + +The following is the example for running the script to setup the Keycloak +server. Before you run the script you should confirm and note at least user_id, +project_id to use in configuring the Keycloak. + +.. code-block:: console + + $ openstack user show nfv_user + +---------------------+----------------------------------+ + | Field | Value | + +---------------------+----------------------------------+ + | default_project_id | None | + | domain_id | default | + | email | None | + | enabled | True | + | id | 35c884d8a6544d38abce33c0003c8331 | + | name | nfv_user | + | description | None | + | password_expires_at | None | + +---------------------+----------------------------------+ + $ openstack project show nfv + +-------------+----------------------------------+ + | Field | Value | + +-------------+----------------------------------+ + | description | | + | domain_id | default | + | enabled | True | + | id | ce5b19a933354bdf87ac6d698494ad47 | + | is_domain | False | + | name | nfv | + | options | {} | + | parent_id | default | + | tags | [] | + +-------------+----------------------------------+ + + +After confirming the required information, run the script file to start +Keycloak server. The script is interactive and will ask required information to +configure Keycloak server. And lastly it will output information required to +configure the Tacker server to use started Keycloak server as authorization +server and curl command to test token endpoint. + +Currently, the script and Tacker APIs supports the following 5 Client +Credentials Grant flows: + +* ``client_secret_post`` +* ``client_secret_basic`` +* ``private_key_jwt`` +* ``client_secret_jwt`` +* ``tls_client_auth`` + +In this guide, the ``client_secret_basic`` client will be used as for an +example to try external authentication. + +.. note:: + + You can see help by using -h or \-\-help option. And you can generate only + Keycloak configuration and realm json only without actually starting the + Keycloak server by providing -n or \-\-no-server option. + + +.. code-block:: console + + $ cd TACKER_ROOT/doc/tools/ext_oauth2_server + $ bash ./gen_keycloak.sh + Select the client credential grant flow type for keycloak server : + 1. client_secret_post + 2. client_secret_basic + 3. private_key_jwt + 4. client_secret_jwt + 5. tls_client_auth + Enter your choice (1-5): 2 + You selected: client_secret_basic + ------------------------- + + Enable Oauth2 certificate-bounded token? (y/n) [default:n] : + Oauth2 certificate-bounded token is disabled + ------------------------- + + Set auth type to client secret basic. + ------------------------- + + Enter OS username[default:nfv_user]: + Successfully set OS username with nfv_user + ------------------------- + + Enter OS user id: 35c884d8a6544d38abce33c0003c8331 + Successfully set OS user id with 35c884d8a6544d38abce33c0003c8331 + ------------------------- + + Enter OS user domain id[default:default]: + Successfully set OS user domain id with default + ------------------------- + + Enter OS user domain name[default:Default]: + Successfully set OS user domain name with default + ------------------------- + + Enter OS project name[default:nfv]: + Successfully set OS project name with nfv + ------------------------- + + Enter OS project id: ce5b19a933354bdf87ac6d698494ad47 + Successfully set OS Project id with ce5b19a933354bdf87ac6d698494ad47 + ------------------------- + + Enter OS project domain id[default:default]: + Successfully set OS project domain id with default + ------------------------- + + Enter OS project domain name[default:Default]: + Successfully set OS project domain name with default + ------------------------- + + Enter OS user roles[default:admin,member,reader]: + Successfully set OS user roles with 'admin,member,reader' + ------------------------- + + Generating Certificate + Certificate files already exist. + Overwrite? (y/n) [default:n]: + Existing file will be used + ------------------------- + + Creating Keycloak config + ------------------------- + + Starting Keycloak Server + + keycloak + keycloak + 64e2422c88cabfae6cb65a87f167a32bd73382bd4c9693e4af9ee23a4264aebc + Waiting Keycloak Server to start...[\] + Keycloak server is started successfully. + ################################### + HTTP endpoint : http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token + HTTPS endpoint : https://$keycloak_host_name:$keycloak_https_port/realms/testrealm/protocol/openid-connect/token + client_id : tacker_service, tacker_api_proj, tacker_api_domain + client_secret : iIK6lARLzJgoQQyMyoymNYrGTDuR0733S + scope : project_scope, domain_scope + * If you want to use other Keycloak server, import this realm.json + realm JSON file : SCRIPT_PATH/etc/keycloak/conf/base_realm.json + * Use the following keys and certificates for Tacker and client + RootCA certificate : SCRIPT_PATH/etc/ssl/localcerts/ca.pem + Tacker certificate : SCRIPT_PATH/etc/ssl/localcerts/tacker.pem + Tacker key : SCRIPT_PATH/etc/ssl/localcerts/tacker.key + client certificate : SCRIPT_PATH/etc/ssl/localcerts/client.pem + client key : SCRIPT_PATH/etc/ssl/localcerts/client.pem + ------------------------------------ + You can try getting a token using following command + + curl -s -X POST http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token \ + -d 'scope=tacker_scope' -d 'client_id=tacker_service' -d 'grant_type=client_credentials' \ + -u 'tacker_service:iIK6lARLzJgoQQyMyoymNYrGTDuR0733S' + ################################### + + +After running the script, Keycloak server will start running. In order to +confirm the server is you can try getting token by using the command from the +output of the script as follow. + +.. code-block:: console + + $ curl -s -X POST http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token \ + -d 'scope=tacker_scope' -d 'client_id=tacker_service' -d 'grant_type=client_credentials' \ + -u 'tacker_service:iIK6lARLzJgoQQyMyoymNYrGTDuR0733S' + + {"access_token":"$access_token","expires_in":300,"refresh_expires_in":0, + "token_type":"Bearer","not-before-policy":0,"scope":""} + + +You can reference the user attributes mapping setting of the scopes and +other settings like each client details by accessing +``http://$keycloak_host_name:$keycloak_http_port/admin/master/console/#/testrealm`` after starting +the keycloak server. The realm json file can also be found in +``{SCRIPT_PATH}/etc/keycloak/conf/base_realm.json`` as you can see in output of +the script. + +The Keycloak server that is configured and started by using the script has +three clients preconfigured. One of them is prepared for Tacker and the other +two are prepared for users. + +.. list-table:: + :header-rows: 1 + :widths: 20 30 25 25 + + * - Name + - Description + - Where it is used + - How to use + * - tacker_service + - A client for Tacker to call the OAuth2.0 token introspection API in + Keycloak + - Tacker -> Keycloak + - Write credentials to tacker.conf + * - tacker_api_proj + - A client for users to call Tacker API with project scoped access token + - User -> Tacker + - Write mapping rules in ``tacker.conf`` and set credentials in requests + to obtain access token from Keycloak + * - tacker_api_domain + - A client for users to call Tacker API with domain scoped access token + - User -> Tacker + - Write mapping rules in ``tacker.conf`` and set credentials in requests + to obtain access token from Keycloak + +The ``tacker_service`` client is used by Tacker to perform OAuth2.0 token +introspection. For this to happen, you need to write the client's credentials +to ``tacker.conf``. + +The ``tacker_api_proj`` and ``tacker_api_domain`` can be used to call Tacker +API. You can choose one of them depending on the scope of the token you need. +The ``tacker_api_proj`` will obtain the project scoped token that is privileged +to access resources in a specific project whereas ``tacker_api_domain`` will +obtain the domain scoped token that is privileged to access resources in a +specific domain (c.f., `project details`_ and `domain details`_). You also need +to write correct mapping rules described later to ``tacker.conf`` so Tacker can +correctly obtain user attributes, such as ``project_id``, ``project_name``, +etc., from access token for subsequent processes. + +In this guide, the ``tacker_api_proj`` client will be used as for an example. + +.. note:: + + If you want to configure those clients manually, please note that if + project's ``id`` and ``name`` claims exist in a token, Keystonemiddleware + will authorize a client for a specific project, otherwise, a client will be + authorized for the project domain. You can find the configured claims in + `Mappers tab of Client scope page in the Keycloak dashboard`_. + + Guide ~~~~~ -.. TODO(Kyaw Myo Thant): Guide to configure Keycloak, configurations and - resource related to the current document should be added. - To use external OAuth 2.0 authorization server for Tacker, you should configure the Tacker server and the Keystonemiddleware in the following steps. @@ -93,21 +327,71 @@ clients and verifies a client's identity. For detail, see and enable Tacker to get an access token from the external OAuth 2.0 authorization server to access other OpenStack services. - If the external OAuth 2.0 authorization server requires HTTPS communication, - you need to specify the CA certificate to the config parameters ``cafile`` - to verify the external OAuth 2.0 authorization server's certificate. If the - config parameter ``insecure`` is set to True, the CA certificate specified - by the config parameter ``cafile`` is not used for verification. + As described before, you need to change ``tacker.conf`` as follows: + + 1. Write credentials of tacker_service client + 2. Write mapping rules for tacker_api_proj client + + You can use the following sample configuration to use keycloak server + started above section. + + .. code-block:: ini + + [DEFAULT] + use_ssl=False + + [ext_oauth2_auth] + use_ext_oauth2_auth=True + token_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token + scope=tacker_scope + introspect_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token/introspect + audience=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm + auth_method=client_secret_basic + client_id=tacker_service + client_secret=iIK6lARLzJgoQQyMyoymNYrGTDuR0733S + insecure=True + thumbprint_verify=False + mapping_project_id=project_info.id + mapping_project_name=project_info.name + mapping_project_domain_id=project_info.domain.id + mapping_project_domain_name=project_info.domain.name + mapping_user_id=user.id + mapping_user_name=user.name + mapping_user_domain_id=user.domain.id + mapping_user_domain_name=user.domain.name + mapping_roles=role_info + + + .. note:: + + If you just want to try external authentication with Tacker, you can skip + the rest part of this step and go to `Verify Access to Tacker APIs`_. + + + If you want to configure Tacker for your specific use case, you need to + change the above parameters appropriately. For example, if the external + OAuth 2.0 authorization server requires HTTPS communication, you need to + specify the CA certificate to the config parameters ``cafile`` to verify + the external OAuth 2.0 authorization server's certificate. If the config + parameter ``insecure`` is set to True, the CA certificate specified by the + config parameter ``cafile`` is not used for verification. If the external OAuth 2.0 authorization server requires mTLS communication, you need to configure the config parameters ``certfile``, ``keyfile`` and ``cafile``. + .. note:: + + In this guide, HTTP is used in all examples except for ``tls_client_auth`` + because mTLS is necessary in ``tls_client_auth`` authentication method. + In production environment, using HTTPS is highly recommended for security. + + If you need to enable Tacker server to use mTLS communication, you must set the config parameter ``use_ssl`` to True and you need to configure the config parameters ``ssl_cert_file``, ``ssl_key_file`` and ``ssl_ca_file``. - You can refer to the :doc:`/admin/configure_tls` to generating the - client/server certificates for mTLS. + For details about setting up HTTPS or mTLS in Tacker, You can refer to the + :doc:`/admin/configure_tls`. If the config parameter ``thumbprint_verify`` is set to True, the token will be verified against the client certificate that used to obtain access token. @@ -131,181 +415,117 @@ clients and verifies a client's identity. For detail, see original logic, get an x-auth-token from the Keystone identity server, and then access the other OpenStack services. - The current Tacker APIs supports the following 5 Client Credentials Grant - flows: - - * ``client_secret_basic`` - * ``client_secret_post`` - * ``private_key_jwt`` - * ``client_secret_jwt`` - * ``tls_client_auth`` - - The following parts is the sample configurations for each method. - * client_secret_basic: - This is sample configuration of ``client_secret_basic`` authentication - method with these requirements: - - * Tacker APIs requires mTLS - * External OAuth 2.0 authorization server requires mTLS - * Token thumbprint confirmation is required - - .. code-block:: console - - [DEFAULT] - use_ssl=True - ssl_ca_file=/etc/tacker/multi_ca.pem - ssl_cert_file=/etc/tacker/tacker_api.pem - ssl_key_file=/etc/tacker/tacker_api.key - - [ext_oauth2_auth] - use_ext_oauth2_auth=True - token_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token - scope=openstack - introspect_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token/introspect - audience=https://$keycloak_host_name:8443/realms/testrealm - auth_method=client_secret_basic - client_id=tacker_service - client_secret=sPocbjFjQCmrPPAXY9IUOVNJ9Cw3rDw5 - certfile=/etc/tacker/tacker_client.pem - keyfile=/etc/tacker/tacker_client.key - cafile=/etc/tacker/multi_ca.pem - insecure=False - thumbprint_verify=True - mapping_project_id=project.id - mapping_project_name=project.name - mapping_project_domain_id=project.domain.id - mapping_project_domain_name=project.domain.name - mapping_user_id=user.id - mapping_user_name=user.name - mapping_user_domain_id=user.domain.id - mapping_user_domain_name=user.domain.name - mapping_roles=user.roles - - * client_secret_post: This is sample configuration of ``client_secret_post`` authentication - method with these requirements: + method: - * Tacker APIs requires HTTPS - * External OAuth 2.0 authorization server doesn't require HTTPS - * Token thumbprint confirmation is not required - - .. code-block:: console + .. code-block:: ini [DEFAULT] - use_ssl=True - ssl_cert_file=/etc/tacker/tacker_api.pem - ssl_key_file=/etc/tacker/tacker_api.key + use_ssl=False [ext_oauth2_auth] use_ext_oauth2_auth=True - token_endpoint=http://$keycloak_host_name:8080/realms/testrealm/protocol/openid-connect/token - scope=openstack - introspect_endpoint=http://$keycloak_host_name:8080/realms/testrealm/protocol/openid-connect/token/introspect - audience=http://$keycloak_host_name:8080/realms/testrealm + token_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token + scope=tacker_scope + introspect_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token/introspect + audience=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm auth_method=client_secret_post client_id=tacker_service - client_secret=sPocbjFjQCmrPPAXY9IUOVNJ9Cw3rDw5 + client_secret=iIK6lARLzJgoQQyMyoymNYrGTDuR0733S insecure=True thumbprint_verify=False - mapping_project_id=project.id - mapping_project_name=project.name - mapping_project_domain_id=project.domain.id - mapping_project_domain_name=project.domain.name + mapping_project_id=project_info.id + mapping_project_name=project_info.name + mapping_project_domain_id=project_info.domain.id + mapping_project_domain_name=project_info.domain.name mapping_user_id=user.id mapping_user_name=user.name mapping_user_domain_id=user.domain.id mapping_user_domain_name=user.domain.name - mapping_roles=user.roles + mapping_roles=role_info * private_key_jwt: This is sample configuration of ``private_key_jwt`` authentication - method with these requirements: + method: - * Tacker APIs doesn't require HTTPS - * External OAuth 2.0 authorization requires HTTPS - * Token thumbprint confirmation is not required + .. note:: - .. code-block:: console + When getting token in ``private_key_jwt`` and ``client_secret_jwt``, + the ``client_assertion`` of the request body is signed JWT that is + locally created and consists of the claims like ``iss``, ``aud``, etc. + The detailed format and claims can be referenced in + `openid-connect 1.0 core specs`_ and `RFC7523`_, and how to create, + encrypt and sign JWT in `RFC7519`_. + + + .. code-block:: ini [DEFAULT] use_ssl=False [ext_oauth2_auth] use_ext_oauth2_auth=True - token_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token - scope=openstack - introspect_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token/introspect - audience=https://$keycloak_host_name:8443/realms/testrealm + token_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token + scope=tacker_scope + introspect_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token/introspect + audience=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm auth_method=private_key_jwt client_id=tacker_service - jwt_key_file=/etc/tacker/private_jwt.key + jwt_key_file=/etc/tacker/private_key.pem jwt_algorithm=RS256 jwt_bearer_time_out=7200 - cafile=/etc/tacker/multi_ca.pem - insecure=False + insecure=True thumbprint_verify=False - mapping_project_id=project.id - mapping_project_name=project.name - mapping_project_domain_id=project.domain.id - mapping_project_domain_name=project.domain.name + mapping_project_id=project_info.id + mapping_project_name=project_info.name + mapping_project_domain_id=project_info.domain.id + mapping_project_domain_name=project_info.domain.name mapping_user_id=user.id mapping_user_name=user.name mapping_user_domain_id=user.domain.id mapping_user_domain_name=user.domain.name - mapping_roles=user.roles + mapping_roles=role_info * client_secret_jwt: This sample configuration of ``client_secret_jwt`` authentication - method with these requirements: + method: - * Tacker APIs doesn't require HTTPS - * External OAuth 2.0 authorization server requires mTLS - * Token thumbprint confirmation is not required - - .. code-block:: console + .. code-block:: ini [DEFAULT] use_ssl=False [ext_oauth2_auth] use_ext_oauth2_auth=True - token_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token - scope=openstack - introspect_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token/introspect - audience=https://$keycloak_host_name:8443/realms/testrealm + token_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token + scope=tacker_scope + introspect_endpoint=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token/introspect + audience=http://$keycloak_host_name:$keycloak_http_port/realms/testrealm auth_method=client_secret_jwt client_id=tacker_service - client_secret=gLQnfhNWrDMk6cKMKgKSALDcpiB2Hk7k - certfile=/etc/tacker/tacker_client.pem - keyfile=/etc/tacker/tacker_client.key + client_secret=iIK6lARLzJgoQQyMyoymNYrGTDuR0733S jwt_algorithm=HS512 jwt_bearer_time_out=7200 - cafile=/etc/tacker/multi_ca.pem - insecure=False + insecure=True thumbprint_verify=False - mapping_project_id=project.id - mapping_project_name=project.name - mapping_project_domain_id=project.domain.id - mapping_project_domain_name=project.domain.name + mapping_project_id=project_info.id + mapping_project_name=project_info.name + mapping_project_domain_id=project_info.domain.id + mapping_project_domain_name=project_info.domain.name mapping_user_id=user.id mapping_user_name=user.name mapping_user_domain_id=user.domain.id mapping_user_domain_name=user.domain.name - mapping_roles=user.roles + mapping_roles=role_info * tls_client_auth: - This sample configuration of ``tls_client_auth`` authentication method - with these requirements: - - * Tacker APIs requires mTLS - * External OAuth 2.0 authorization server requires mTLS - * Token thumbprint confirmation is required + This sample configuration of ``tls_client_auth`` authentication method: .. note:: @@ -313,7 +533,7 @@ clients and verifies a client's identity. For detail, see necessary when ``tls_client_auth`` is being used for authentication. - .. code-block:: console + .. code-block:: ini [DEFAULT] use_ssl=True @@ -323,26 +543,26 @@ clients and verifies a client's identity. For detail, see [ext_oauth2_auth] use_ext_oauth2_auth=True - token_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token - scope=openstack - introspect_endpoint=https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token/introspect - audience=https://$keycloak_host_name:8443/realms/testrealm + token_endpoint=https://$keycloak_host_name:$keycloak_https_port/realms/testrealm/protocol/openid-connect/token + scope=tacker_scope + introspect_endpoint=https://$keycloak_host_name:$keycloak_https_port/realms/testrealm/protocol/openid-connect/token/introspect + audience=https://$keycloak_host_name:$keycloak_https_port/realms/testrealm auth_method=tls_client_auth client_id=tacker_service certfile=/etc/tacker/tacker_client.pem keyfile=/etc/tacker/tacker_client.key - cafile=/etc/tacker/multi_ca.pem + cafile=/etc/tacker/ca.pem insecure=False thumbprint_verify=True - mapping_project_id=project.id - mapping_project_name=project.name - mapping_project_domain_id=project.domain.id - mapping_project_domain_name=project.domain.name + mapping_project_id=project_info.id + mapping_project_name=project_info.name + mapping_project_domain_id=project_info.domain.id + mapping_project_domain_name=project_info.domain.name mapping_user_id=user.id mapping_user_name=user.name mapping_user_domain_id=user.domain.id mapping_user_domain_name=user.domain.name - mapping_roles=user.roles + mapping_roles=role_info 3. Restart Tacker service so that the modified configuration information takes @@ -354,6 +574,8 @@ clients and verifies a client's identity. For detail, see $ sudo systemctl restart devstack@tacker-conductor.service +.. _Verify Access to Tacker APIs: + Verify Access to Tacker APIs ---------------------------- @@ -376,335 +598,327 @@ external OAuth 2.0 Authentication server: 3. Check the access token of the introspect API provided by `Keycloak`_ from the Tacker server logs. -The following parts is the examples for each of the 5 authentication methods. -The Tacker configuration used for each example can be referred to previous -chapter. +The requests for the verification are different depending on the authentication +methods. As Keycloak is configured to use ``client_secret_basic`` in this +guide, you can use the following example. -* client_secret_basic: - When the `Keycloak`_ server requires to use the mTLS protocol and - the ``client_secret_basic`` authentication method: +.. code-block:: console - .. code-block:: console + $ curl -i -X POST http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token \ + -u "tacker_api_proj:iIK6lARLzJgoQQyMyoymNYrGTDuR0733S" \ + -d "scope=project_scope" -d "grant_type=client_credentials" + HTTP/1.1 200 OK + Cache-Control: no-store + Pragma: no-cache + content-length: 1773 + Content-Type: application/json + Referrer-Policy: no-referrer + Strict-Transport-Security: max-age=31536000; includeSubDomains + X-Content-Type-Options: nosniff + X-Frame-Options: SAMEORIGIN + X-XSS-Protection: 1; mode=block - $ curl -i -X POST https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token \ - -u tacker_service:sPocbjFjQCmrPPAXY9IUOVNJ9Cw3rDw5 \ - -d "scope=openstack" \ - -d "grant_type=client_credentials" \ - --cacert multi_ca.pem \ - --key client.key \ - --cert client.pem - HTTP/2 200 - cache-control: no-store - pragma: no-cache - content-length: 1873 - content-type: application/json - referrer-policy: no-referrer - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - x-frame-options: SAMEORIGIN - x-xss-protection: 1; mode=block - {"access_token":"$oauth2_access_token", - "expires_in":300,"refresh_expires_in":0, - "token_type":"Bearer","not-before-policy":0, - "scope":"openstack"} + {"access_token":"$access_token","expires_in":300,"refresh_expires_in":0, + "token_type":"Bearer","not-before-policy":0,"scope":"email profile"} - $ curl -i -X GET https://$tacker_host_name:9890/v1.0/vims \ - -H "Authorization: Bearer $oauth2_access_token" \ - --cacert multi_ca.pem \ - --key client.key \ - --cert client.pem - HTTP/1.1 200 OK - Content-Type: application/json - Content-Length: 2182 - X-Openstack-Request-Id: req-7c1abeac-2179-4dde-b3e7-639b16853ca3 - Date: Mon, 09 Sep 2024 01:30:59 GMT - {"vims": [{"id": "ce04bbe5-3ffe-449f-ba2a-69c0a747b9ad", "type": "kubernetes", - "tenant_id": "2e189ea6c1df4e4ba6d89de254b3a534", "name": "test-vim-k8s", - "description": "", "placement_attr": {"regions": ["default", "kube-node-lease", - "kube-public", "kube-system"]}, "is_default": true, "created_at": "2024-07-04 09:07:56", - "updated_at": null, "extra": {}, "auth_url": "https://10.0.2.15:6443", - "vim_project": {"name": "nfv"}, "auth_cred": {"bearer_token": "***", - "ssl_ca_cert": "gAAAAABmhm.....oN2Ps5SOO6yhOF_4w==", "auth_url": - "https://10.0.2.15:6443", "username": "None", "key_type": "barbican_key", - "secret_uuid": "***"}, "status": "ACTIVE"}]} - $ tail -f /opt/stack/log/tacker-server.log - DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: - {'exp': 1725845511, 'iat': 1725845211, 'jti': '79c8bc7b-b29e-484a-afde-1bab169ce482', - 'iss': 'https://$keycloak_host_name:8443/realms/testrealm', 'aud': 'account', - 'sub': '7e3c5cb5-48a4-460c-b206-b8dca2ea0c36', 'typ': 'Bearer', - 'azp': 'tacker_service', 'acr': '1', 'allowed-origins': ['https://127.0.0.1:9890/'], - 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, - 'resource_access': {'tacker_service': {'roles': ['uma_protection']}, - 'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, - 'cnf': {'x5t#S256': 'YGhr3eS01OTAAxAeksVwNc22gDnB-SSJPL7Y1BuqKvo'}, 'scope': 'openstack', - 'project': {'domain': {'name': 'Default', 'id': 'default'}, - 'name': 'nfv', 'id': '2e189ea6c1df4e4ba6d89de254b3a534'}, - 'preferred_username': 'service-account-tacker_service', - 'user': {'domain': {'name': 'Default', 'id': 'default'}, - 'roles': 'admin', 'name': 'nfv_user', 'id': '173c59254d3040969e359e5df0a3b475'}, - 'client_id': 'tacker_service', 'username': 'service-account-tacker_service', - 'token_type': 'Bearer', 'active': True} _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:732 + $ curl -i -X GET http://$tacker_host_name:9890/v1.0/vims \ + -H "Authorization: Bearer $access_token" + HTTP/1.1 200 OK + Content-Type: application/json + Content-Length: 743 + X-Openstack-Request-Id: req-2f954ee7-e6fd-4d53-ac31-bf8c7d9245d7 + Date: Tue, 17 Dec 2024 06:27:24 GMT + + {"vims": [{"id": "a99189da-bf72-4af7-884c-36d157f00571", + "type": "openstack", "tenant_id": "2cc02f60acf34fdda7bc5e9af9a7032b", + "name": "openstack", "description": "", "placement_attr": { + "regions": ["RegionOne"]}, "is_default": true, + "created_at": "2024-11-07 02:04:46", "updated_at": "2024-11-07 02:10:18", + "extra": {}, "auth_url": "http://192.168.56.11/identity/v3", + "vim_project": {"name": "admin", "project_domain_name": "default"}, + "auth_cred": {"username": "admin", "user_domain_name": "default", + "cert_verify": "True", "project_id": null, "project_name": "admin", + "project_domain_name": "default", "auth_url": "http://192.168.56.11/identity/v3", + "key_type": "barbican_key", "secret_uuid": "***", "password": "***"}, "status": "ACTIVE"}]} + + $ tail -f /opt/stack/log/tacker-server.log + Dec 17 05:45:25 controller-tacker tacker-server[835]: + DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: { + 'exp': 1734414535, 'iat': 1734414235, 'jti': '49458c8f-507d-4d08-a81f-c3a6ee484190', + 'iss': 'http://$keycloak_host_name:$keycloak_http_port/realms/testrealm', 'aud': 'account', 'sub': '7d3e5929-4bbe-4ef4-90e3-8fd4b445ed7f', + 'typ': 'Bearer', 'azp': 'tacker_api_proj', 'acr': '1', 'allowed-origins': ['/*'], + 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, + 'resource_access': {'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, + 'scope': 'email profile', 'email_verified': False, 'role_info': 'admin,member,reader', + 'preferred_username': 'service-account-tacker_api_proj', 'user': {'domain': {'name': 'default', 'id': 'default'}, + 'name': 'nfv_user', 'id': '35c884d8a6544d38abce33c0003c8331'}, 'project_info': {'domain': {'id': 'default', 'name': 'Default'}, + 'id': 'ce5b19a933354bdf87ac6d698494ad47', 'name': 'nfv'}, 'client_id': 'tacker_api_proj', + 'username': 'service-account-tacker_api_proj', 'token_type': 'Bearer', 'active': True} + {{(pid=835) _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:731}} + + +If you configure Keycloak with another authentication method, please see +examples below. * client_secret_post: - When the `Keycloak`_ server requires to use the HTTP protocol and - the ``client_secret_post`` authentication method: - .. code-block:: console + .. code-block:: console - $ curl -i -X POST http://$keycloak_host_name:8080/realms/testrealm/protocol/openid-connect/token \ - -d "client_id=tacker_service" -d "client_secret=sPocbjFjQCmrPPAXY9IUOVNJ9Cw3rDw5" \ - -d "scope=openstack" \ - -d "grant_type=client_credentials" - HTTP/1.1 200 OK - Cache-Control: no-store - Pragma: no-cache - content-length: 1785 - Content-Type: application/json - Referrer-Policy: no-referrer - Strict-Transport-Security: max-age=31536000; includeSubDomains - X-Content-Type-Options: nosniff - X-Frame-Options: SAMEORIGIN - X-XSS-Protection: 1; mode=block - {"access_token":"$oauth2_access_token", - "expires_in":300,"refresh_expires_in":0, - "token_type":"Bearer","not-before-policy":0, - "scope":"openstack"} + $ curl -i -X POST http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token \ + -d "client_id=tacker_api_proj" -d "client_secret=iIK6lARLzJgoQQyMyoymNYrGTDuR0733S" \ + -d "scope=project_scope" -d "grant_type=client_credentials" + HTTP/1.1 200 OK + Cache-Control: no-store + Pragma: no-cache + content-length: 1773 + Content-Type: application/json + Referrer-Policy: no-referrer + Strict-Transport-Security: max-age=31536000; includeSubDomains + X-Content-Type-Options: nosniff + X-Frame-Options: SAMEORIGIN + X-XSS-Protection: 1; mode=block - $ curl -i -X GET https://$tacker_host_name:9890/v1.0/vims \ - -H "Authorization: Bearer $oauth2_access_token" \ - --cacert multi_ca.pem - HTTP/1.1 200 OK - Content-Type: application/json - Content-Length: 2182 - X-Openstack-Request-Id: req-1960f278-82db-4ccf-81a1-be0839c024d2 - Date: Mon, 09 Sep 2024 02:02:59 GMT - {"vims": [{"id": "ce04bbe5-3ffe-449f-ba2a-69c0a747b9ad", "type": "kubernetes", - "tenant_id": "2e189ea6c1df4e4ba6d89de254b3a534", "name": "test-vim-k8s", - "description": "", "placement_attr": {"regions": ["default", "kube-node-lease", - "kube-public", "kube-system"]}, "is_default": true, "created_at": "2024-07-04 09:07:56", - "updated_at": null, "extra": {}, "auth_url": "https://10.0.2.15:6443", - "vim_project": {"name": "nfv"}, "auth_cred": {"bearer_token": "***", - "ssl_ca_cert": "gAAAAABmhm.....oN2Ps5SOO6yhOF_4w==", "auth_url": - "https://10.0.2.15:6443", "username": "None", "key_type": "barbican_key", - "secret_uuid": "***"}, "status": "ACTIVE"}]} + {"access_token":"$access_token","expires_in":300,"refresh_expires_in":0, + "token_type":"Bearer","not-before-policy":0,"scope":"email profile"} - $ tail -f /opt/stack/log/tacker-server.log - DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: - {'exp': 1725847413, 'iat': 1725847113, 'jti': 'db3bb08e-3b78-4c5b-9a62-6c382401d31a', - 'iss': 'http://$keycloak_host_name:8080/realms/testrealm', 'aud': 'account', - 'sub': '7e3c5cb5-48a4-460c-b206-b8dca2ea0c36', 'typ': 'Bearer', - 'azp': 'tacker_service', 'acr': '1', 'allowed-origins': ['https://127.0.0.1:9890/'], - 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, - 'resource_access': {'tacker_service': {'roles': ['uma_protection']}, - 'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, - 'scope': 'openstack', 'project': {'domain': {'name': 'Default', 'id': 'default'}, - 'name': 'nfv', 'id': '2e189ea6c1df4e4ba6d89de254b3a534'}, 'preferred_username': - 'service-account-tacker_service', 'user': {'domain': {'name': 'Default', 'id': 'default'}, - 'roles': 'admin', 'name': 'nfv_user', 'id': '173c59254d3040969e359e5df0a3b475'}, - 'client_id': 'tacker_service', 'username': 'service-account-tacker_service', - 'token_type': 'Bearer', 'active': True} _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:732 + $ curl -i -X GET http://$tacker_host_name:9890/v1.0/vims \ + -H "Authorization: Bearer $access_token" + HTTP/1.1 200 OK + Content-Type: application/json + Content-Length: 743 + X-Openstack-Request-Id: req-2cb42224-8293-4deb-b772-9aeff5354922 + Date: Fri, 06 Dec 2024 08:56:38 GMT + + {"vims": [{"id": "a99189da-bf72-4af7-884c-36d157f00571", + "type": "openstack", "tenant_id": "2cc02f60acf34fdda7bc5e9af9a7032b", + "name": "openstack", "description": "", "placement_attr": { + "regions": ["RegionOne"]}, "is_default": true, + "created_at": "2024-11-07 02:04:46", "updated_at": "2024-11-07 02:10:18", + "extra": {}, "auth_url": "http://192.168.56.11/identity/v3", + "vim_project": {"name": "admin", "project_domain_name": "default"}, + "auth_cred": {"username": "admin", "user_domain_name": "default", + "cert_verify": "True", "project_id": null, "project_name": "admin", + "project_domain_name": "default", "auth_url": "http://192.168.56.11/identity/v3", + "key_type": "barbican_key", "secret_uuid": "***", "password": "***"}, "status": "ACTIVE"}]} + + $ tail -f /opt/stack/log/tacker-server.log + Dec 06 08:56:38 controller-tacker tacker-server[20354]: + DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: { + 'exp': 1733475612, 'iat': 1733475312, 'jti': '946ef21c-17c2-4416-ac6a-37d9ef9f5739', + 'iss': 'http://$keycloak_host_name:$keycloak_http_port/realms/testrealm', 'aud': 'account', 'sub': '7d3e5929-4bbe-4ef4-90e3-8fd4b445ed7f', + 'typ': 'Bearer', 'azp': 'tacker_api_proj', 'acr': '1', 'allowed-origins': ['/*'], + 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, + 'resource_access': {'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, + 'scope': 'email profile', 'email_verified': False, 'role_info': 'admin,member,reader', + 'preferred_username': 'service-account-tacker_api_proj', 'user': {'domain': {'name': 'default', 'id': 'default'}, + 'name': 'nfv_user', 'id': '35c884d8a6544d38abce33c0003c8331'}, 'project_info': {'domain': { + 'id': 'default', 'name': 'Default'}, 'id': 'ce5b19a933354bdf87ac6d698494ad47', 'name': 'nfv'}, + 'client_id': 'tacker_api_proj', 'username': 'service-account-tacker_api_proj', 'token_type': 'Bearer', 'active': True} + {{(pid=20354) _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:731}} * private_key_jwt: - When the `Keycloak`_ server requires to use the HTTPS protocol and - the ``private_key_jwt`` authentication method: - .. code-block:: console + .. code-block:: console - $ curl -i -X POST https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token \ - -d "client_id=tacker_service" \ - -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ - -d "client_assertion=eyJhbGciOiJS.....EOr5ndYF4I6qg" \ - -d "grant_type=client_credentials" \ - --cacert multi_ca.pem - HTTP/2 200 - cache-control: no-store - pragma: no-cache - content-length: 1786 - content-type: application/json - referrer-policy: no-referrer - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - x-frame-options: SAMEORIGIN - x-xss-protection: 1; mode=block - {"access_token":"$oauth2_access_token", - "expires_in":300,"refresh_expires_in":0, - "token_type":"Bearer","not-before-policy":0, - "scope":"openstack"} + $ curl -i -X POST http://$keycloak_host_name:$keycloak_http_port/realms/testrealm/protocol/openid-connect/token \ + -d "client_id=tacker_api_proj" -d "scope=project_scope" -d "grant_type=client_credentials" \ + -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ + -d "client_assertion=$client_assertion" + HTTP/1.1 200 OK + Cache-Control: no-store + Pragma: no-cache + content-length: 1774 + Content-Type: application/json + Referrer-Policy: no-referrer + Strict-Transport-Security: max-age=31536000; includeSubDomains + X-Content-Type-Options: nosniff + X-Frame-Options: SAMEORIGIN + X-XSS-Protection: 1; mode=block - $ curl -i -X GET http://$tacker_host_name:9890/v1.0/vims \ - -H "Authorization: Bearer $oauth2_access_token" \ - HTTP/1.1 200 OK - Content-Type: application/json - Content-Length: 2182 - X-Openstack-Request-Id: req-9c287081-bd0b-4e43-ae80-06acfa1ca3a2 - Date: Mon, 09 Sep 2024 03:17:02 GMT - {"vims": [{"id": "ce04bbe5-3ffe-449f-ba2a-69c0a747b9ad", "type": "kubernetes", - "tenant_id": "2e189ea6c1df4e4ba6d89de254b3a534", "name": "test-vim-k8s", - "description": "", "placement_attr": {"regions": ["default", "kube-node-lease", - "kube-public", "kube-system"]}, "is_default": true, "created_at": "2024-07-04 09:07:56", - "updated_at": null, "extra": {}, "auth_url": "https://10.0.2.15:6443", - "vim_project": {"name": "nfv"}, "auth_cred": {"bearer_token": "***", - "ssl_ca_cert": "gAAAAABmhm.....oN2Ps5SOO6yhOF_4w==", "auth_url": - "https://10.0.2.15:6443", "username": "None", "key_type": "barbican_key", - "secret_uuid": "***"}, "status": "ACTIVE"}]} + {"access_token":"$access_token","expires_in":300,"refresh_expires_in":0, + "token_type":"Bearer","not-before-policy":0,"scope":"email profile"} - $ tail -f /opt/stack/log/tacker-server.log - DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: - {'exp': 1725852092, 'iat': 1725851792, 'jti': '3e61de0d-dc23-4a96-a08f-cce233e5a205', - 'iss': 'https://$keycloak_host_name:8443/realms/testrealm', 'aud': 'account', - 'sub': '7e3c5cb5-48a4-460c-b206-b8dca2ea0c36', 'typ': 'Bearer', - 'azp': 'tacker_service', 'acr': '1', 'allowed-origins': ['https://127.0.0.1:9890/'], - 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, - 'resource_access': {'tacker_service': {'roles': ['uma_protection']}, - 'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, - 'scope': 'openstack', 'project': {'domain': {'name': 'Default', 'id': 'default'}, - 'name': 'nfv', 'id': '2e189ea6c1df4e4ba6d89de254b3a534'}, - 'preferred_username': 'service-account-tacker_service', - 'user': {'domain': {'name': 'Default', 'id': 'default'}, 'roles': 'admin', - 'name': 'nfv_user', 'id': '173c59254d3040969e359e5df0a3b475'}, 'client_id': 'tacker_service', - 'username': 'service-account-tacker_service', 'token_type': 'Bearer', - 'active': True} _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:732 + $ curl -i -X GET http://$tacker_host_name:9890/v1.0/vims \ + -H "Authorization: Bearer $access_token" + HTTP/1.1 200 OK + Content-Type: application/json + Content-Length: 743 + X-Openstack-Request-Id: req-b4c07ca6-49c8-4c12-be51-248c507183b9 + Date: Fri, 06 Dec 2024 09:15:07 GMT + + {"vims": [{"id": "a99189da-bf72-4af7-884c-36d157f00571", + "type": "openstack", "tenant_id": "2cc02f60acf34fdda7bc5e9af9a7032b", + "name": "openstack", "description": "", "placement_attr": { + "regions": ["RegionOne"]}, "is_default": true, + "created_at": "2024-11-07 02:04:46", "updated_at": "2024-11-07 02:10:18", + "extra": {}, "auth_url": "http://192.168.56.11/identity/v3", + "vim_project": {"name": "admin", "project_domain_name": "default"}, + "auth_cred": {"username": "admin", "user_domain_name": "default", + "cert_verify": "True", "project_id": null, "project_name": "admin", + "project_domain_name": "default", "auth_url": "http://192.168.56.11/identity/v3", + "key_type": "barbican_key", "secret_uuid": "***", "password": "***"}, "status": "ACTIVE"}]} + + $ tail -f /opt/stack/log/tacker-server.log + Dec 06 09:15:07 controller-tacker tacker-server[21835]: + DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: { + 'exp': 1733476670, 'iat': 1733476370, 'jti': '8c9cf64f-f0f3-4d74-8b15-a6bda7036f07', + 'iss': 'http://$keycloak_host_name:$keycloak_http_port/realms/testrealm', 'aud': 'account', 'sub': '7d3e5929-4bbe-4ef4-90e3-8fd4b445ed7f', + 'typ': 'Bearer', 'azp': 'tacker_api_proj', 'acr': '1', 'allowed-origins': ['/*'], 'realm_access': { + 'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, 'resource_access': {'account': { + 'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, 'scope': 'email profile', + 'email_verified': False, 'role_info': 'admin,member,reader', 'preferred_username': 'service-account-tacker_api_proj', + 'user': {'domain': {'name': 'default', 'id': 'default'}, 'name': 'nfv_user', 'id': '35c884d8a6544d38abce33c0003c8331'}, + 'project_info': {'domain': {'id': 'default', 'name': 'Default'}, 'id': 'ce5b19a933354bdf87ac6d698494ad47', 'name': 'nfv'}, + 'client_id': 'tacker_api_proj', 'username': 'service-account-tacker_api_proj', 'token_type': 'Bearer', 'active': True} + {{(pid=21835) _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:731}} * client_secret_jwt: - When the `Keycloak`_ server requires to use the mTLS protocol and - the ``client_secret_jwt`` authentication method: - .. code-block:: console + .. code-block:: console - $ curl -i -X POST https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token \ - -d "client_id=tacker_service" \ - -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ - -d "client_assertion=eyJhbGciOiJIUzUx.....UVZ11WvcKg" \ - -d "grant_type=client_credentials" \ - --cacert multi_ca.pem \ - --key client.key \ - --cert client.pem - HTTP/2 200 - cache-control: no-store - pragma: no-cache - content-length: 1786 - content-type: application/json - referrer-policy: no-referrer - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - x-frame-options: SAMEORIGIN - x-xss-protection: 1; mode=block - {"access_token":"$oauth2_access_token", - "expires_in":300,"refresh_expires_in":0, - "token_type":"Bearer","not-before-policy":0, - "scope":"openstack"} + $ curl -i -X POST http://$keycloak_host_name:$keycloak_https_port/realms/testrealm/protocol/openid-connect/token \ + -d "client_id=tacker_api_proj" -d "scope=project_scope" -d "grant_type=client_credentials" \ + -d "client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \ + -d "client_assertion=$client_assertion" + HTTP/1.1 200 OK + Cache-Control: no-store + Pragma: no-cache + content-length: 1774 + Content-Type: application/json + Referrer-Policy: no-referrer + Strict-Transport-Security: max-age=31536000; includeSubDomains + X-Content-Type-Options: nosniff + X-Frame-Options: SAMEORIGIN + X-XSS-Protection: 1; mode=block - $ curl -i -X GET http://$tacker_host_name:9890/v1.0/vims \ - -H "Authorization: Bearer $oauth2_access_token" \ - HTTP/1.1 200 OK - Content-Type: application/json - Content-Length: 2182 - X-Openstack-Request-Id: req-777f61b4-e9ea-40b8-90ef-ad1a628070eb - Date: Mon, 09 Sep 2024 05:19:48 GMT - {"vims": [{"id": "ce04bbe5-3ffe-449f-ba2a-69c0a747b9ad", "type": "kubernetes", - "tenant_id": "2e189ea6c1df4e4ba6d89de254b3a534", "name": "test-vim-k8s", - "description": "", "placement_attr": {"regions": ["default", "kube-node-lease", - "kube-public", "kube-system"]}, "is_default": true, "created_at": "2024-07-04 09:07:56", - "updated_at": null, "extra": {}, "auth_url": "https://10.0.2.15:6443", - "vim_project": {"name": "nfv"}, "auth_cred": {"bearer_token": "***", - "ssl_ca_cert": "gAAAAABmhm.....oN2Ps5SOO6yhOF_4w==", "auth_url": - "https://10.0.2.15:6443", "username": "None", "key_type": "barbican_key", - "secret_uuid": "***"}, "status": "ACTIVE"}]} + {"access_token":"$access_token","expires_in":300,"refresh_expires_in":0, + "token_type":"Bearer","not-before-policy":0,"scope":"email profile"} - $ tail -f /opt/stack/log/tacker-server.log - DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: - {'exp': 1725859285, 'iat': 1725858985, 'jti': '9b93e2db-f948-48c3-bd75-acae1da70861', - 'iss': 'https://$keycloak_host_name:8443/realms/testrealm', 'aud': 'account', - 'sub': '7e3c5cb5-48a4-460c-b206-b8dca2ea0c36', 'typ': 'Bearer', - 'azp': 'tacker_service', 'acr': '1', 'allowed-origins': ['https://127.0.0.1:9890/'], - 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, - 'resource_access': {'tacker_service': {'roles': ['uma_protection']}, - 'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, - 'scope': 'openstack', 'project': {'domain': {'name': 'Default', 'id': 'default'}, - 'name': 'nfv', 'id': '2e189ea6c1df4e4ba6d89de254b3a534'}, 'preferred_username': 'service-account-tacker_service', - 'user': {'domain': {'name': 'Default', 'id': 'default'}, - 'roles': 'admin', 'name': 'nfv_user', 'id': '173c59254d3040969e359e5df0a3b475'}, - 'client_id': 'tacker_service', 'username': 'service-account-tacker_service', - 'token_type': 'Bearer', 'active': True} _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:732 + $ curl -i -X GET http://$tacker_host_name:9890/v1.0/vims \ + -H "Authorization: Bearer $access_token" + HTTP/1.1 200 OK + Content-Type: application/json + Content-Length: 743 + X-Openstack-Request-Id: req-4c2e2c76-672e-4517-ac2e-0a79a48b9122 + Date: Fri, 06 Dec 2024 09:28:24 GMT + + {"vims": [{"id": "a99189da-bf72-4af7-884c-36d157f00571", + "type": "openstack", "tenant_id": "2cc02f60acf34fdda7bc5e9af9a7032b", + "name": "openstack", "description": "", "placement_attr": { + "regions": ["RegionOne"]}, "is_default": true, + "created_at": "2024-11-07 02:04:46", "updated_at": "2024-11-07 02:10:18", + "extra": {}, "auth_url": "http://192.168.56.11/identity/v3", + "vim_project": {"name": "admin", "project_domain_name": "default"}, + "auth_cred": {"username": "admin", "user_domain_name": "default", + "cert_verify": "True", "project_id": null, "project_name": "admin", + "project_domain_name": "default", "auth_url": "http://192.168.56.11/identity/v3", + "key_type": "barbican_key", "secret_uuid": "***", "password": "***"}, "status": "ACTIVE"}]} + + $ tail -f /opt/stack/log/tacker-server.log + Dec 06 09:28:23 controller-tacker tacker-server[22701]: + DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: { + 'exp': 1733477523, 'iat': 1733477223, 'jti': '7c07a9ac-3af8-44c7-a243-f2faed10cac0', + 'iss': 'http://$keycloak_host_name:$keycloak_http_port/realms/testrealm', 'aud': 'account', 'sub': '7d3e5929-4bbe-4ef4-90e3-8fd4b445ed7f', + 'typ': 'Bearer', 'azp': 'tacker_api_proj', 'acr': '1', 'allowed-origins': ['/*'], 'realm_access': { + 'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, 'resource_access': {'account': { + 'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, 'scope': 'email profile', + 'email_verified': False, 'role_info': 'admin,member,reader', 'preferred_username': 'service-account-tacker_api_proj', + 'user': {'domain': {'name': 'default', 'id': 'default'}, 'name': 'nfv_user', 'id': '35c884d8a6544d38abce33c0003c8331'}, + 'project_info': {'domain': {'id': 'default', 'name': 'Default'}, 'id': 'ce5b19a933354bdf87ac6d698494ad47', 'name': 'nfv'}, + 'client_id': 'tacker_api_proj', 'username': 'service-account-tacker_api_proj', 'token_type': 'Bearer', 'active': True} + {{(pid=22701) _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:731}} * tls_client_auth: - When the `Keycloak`_ server requires to use the mTLS protocol and - the ``tls_client_auth`` authentication method: - .. code-block:: console + .. code-block:: console - $ curl -i -X POST https://$keycloak_host_name:8443/realms/testrealm/protocol/openid-connect/token \ - -d "client_id=tacker_service" \ - -d "scope=openstack" \ - -d "grant_type=client_credentials" \ - --cacert multi_ca.pem \ - --key client.key \ - --cert client.pem - HTTP/2 200 - cache-control: no-store - pragma: no-cache - content-length: 1786 - content-type: application/json - referrer-policy: no-referrer - strict-transport-security: max-age=31536000; includeSubDomains - x-content-type-options: nosniff - x-frame-options: SAMEORIGIN - x-xss-protection: 1; mode=block - {"access_token":"$oauth2_access_token", - "expires_in":300,"refresh_expires_in":0, - "token_type":"Bearer","not-before-policy":0, - "scope":"openstack"} + $ curl -i -X POST https://$keycloak_host_name:$keycloak_https_port/realms/testrealm/protocol/openid-connect/token \ + -d "client_id=tacker_api_proj" -d "scope=project_scope" -d "grant_type=client_credentials" \ + --cacert ca.pem \ + --cert client.pem \ + --key client.key + HTTP/2 200 + cache-control: no-store + pragma: no-cache + content-length: 1861 + content-type: application/json + referrer-policy: no-referrer + strict-transport-security: max-age=31536000; includeSubDomains + x-content-type-options: nosniff + x-frame-options: SAMEORIGIN + x-xss-protection: 1; mode=block - $ curl -i -X GET https://$tacker_host_name:9890/v1.0/vims \ - -H "Authorization: Bearer $oauth2_access_token" \ - --cacert multi_ca.pem \ - --key client.key \ - --cert client.pem - HTTP/1.1 200 OK - Content-Type: application/json - Content-Length: 2182 - X-Openstack-Request-Id: req-10d08c2c-acc1-4d77-8029-4718381ce704 - Date: Mon, 09 Sep 2024 05:47:39 GMT - {"vims": [{"id": "ce04bbe5-3ffe-449f-ba2a-69c0a747b9ad", "type": "kubernetes", - "tenant_id": "2e189ea6c1df4e4ba6d89de254b3a534", "name": "test-vim-k8s", - "description": "", "placement_attr": {"regions": ["default", "kube-node-lease", - "kube-public", "kube-system"]}, "is_default": true, "created_at": "2024-07-04 09:07:56", - "updated_at": null, "extra": {}, "auth_url": "https://10.0.2.15:6443", - "vim_project": {"name": "nfv"}, "auth_cred": {"bearer_token": "***", - "ssl_ca_cert": "gAAAAABmhm.....oN2Ps5SOO6yhOF_4w==", "auth_url": - "https://10.0.2.15:6443", "username": "None", "key_type": "barbican_key", - "secret_uuid": "***"}, "status": "ACTIVE"}]} + {"access_token":"$access_token","expires_in":300,"refresh_expires_in":0, + "token_type":"Bearer","not-before-policy":0,"scope":"email profile"} - $ tail -f /opt/stack/log/tacker-server.log - DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: - {'exp': 1725861128, 'iat': 1725860828, 'jti': '72d45cb4-ee3c-4c00-b137-be603612761f', - 'iss': 'https://$keycloak_host_name:8443/realms/testrealm', 'aud': 'account', - 'sub': '7e3c5cb5-48a4-460c-b206-b8dca2ea0c36', 'typ': 'Bearer', - 'azp': 'tacker_service', 'acr': '1', 'allowed-origins': ['https://127.0.0.1:9890/'], - 'realm_access': {'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, - 'resource_access': {'tacker_service': {'roles': ['uma_protection']}, - 'account': {'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, - 'cnf': {'x5t#S256': 'YGhr3eS01OTAAxAeksVwNc22gDnB-SSJPL7Y1BuqKvo'}, 'scope': 'openstack', - 'project': {'domain': {'name': 'Default', 'id': 'default'}, - 'name': 'nfv', 'id': '2e189ea6c1df4e4ba6d89de254b3a534'}, - 'preferred_username': 'service-account-tacker_service', - 'user': {'domain': {'name': 'Default', 'id': 'default'}, - 'roles': 'admin', 'name': 'nfv_user', 'id': '173c59254d3040969e359e5df0a3b475'}, - 'client_id': 'tacker_service', 'username': 'service-account-tacker_service', 'token_type': 'Bearer', - 'active': True} _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:732 + $ curl -i -X GET https://$tacker_host_name:9890/v1.0/vims \ + -H "Authorization: Bearer $access_token" \ + --cacert ca.pem \ + --cert client.pem \ + --key client.key + HTTP/1.1 200 OK + Content-Type: application/json + Content-Length: 743 + X-Openstack-Request-Id: req-80b670f0-910f-4d53-9859-6d430f4ba7db + Date: Fri, 06 Dec 2024 09:42:36 GMT + + {"vims": [{"id": "a99189da-bf72-4af7-884c-36d157f00571", + "type": "openstack", "tenant_id": "2cc02f60acf34fdda7bc5e9af9a7032b", + "name": "openstack", "description": "", "placement_attr": { + "regions": ["RegionOne"]}, "is_default": true, + "created_at": "2024-11-07 02:04:46", "updated_at": "2024-11-07 02:10:18", + "extra": {}, "auth_url": "http://192.168.56.11/identity/v3", + "vim_project": {"name": "admin", "project_domain_name": "default"}, + "auth_cred": {"username": "admin", "user_domain_name": "default", + "cert_verify": "True", "project_id": null, "project_name": "admin", + "project_domain_name": "default", "auth_url": "http://192.168.56.11/identity/v3", + "key_type": "barbican_key", "secret_uuid": "***", "password": "***"}, "status": "ACTIVE"}]} + + $ tail -f /opt/stack/log/tacker-server.log + Dec 06 09:42:36 controller-tacker tacker-server[25048]: + DEBUG keystonemiddleware.external_oauth2_token [-] The introspect API response: { + 'exp': 1733478427, 'iat': 1733478127, 'jti': 'a51dbc9c-45b0-46ef-953e-71278b09c9d4', + 'iss': 'https://$keycloak_host_name:$keycloak_https_port/realms/testrealm', 'aud': 'account', 'sub': '7d3e5929-4bbe-4ef4-90e3-8fd4b445ed7f', + 'typ': 'Bearer', 'azp': 'tacker_api_proj', 'acr': '1', 'allowed-origins': ['/*'], 'realm_access': { + 'roles': ['offline_access', 'uma_authorization', 'default-roles-testrealm']}, 'resource_access': {'account': { + 'roles': ['manage-account', 'manage-account-links', 'view-profile']}}, + 'cnf': {'x5t#S256': 'dAHdSS_CN-KNN9jgE8brrkFEDC2uWAKnMslE84CBB38'}, 'scope': 'email profile', + 'email_verified': False, 'role_info': 'admin,member,reader', 'preferred_username': 'service-account-tacker_api_proj', + 'user': {'domain': {'name': 'default', 'id': 'default'}, 'name': 'nfv_user', 'id': '35c884d8a6544d38abce33c0003c8331'}, + 'project_info': {'domain': {'id': 'default', 'name': 'Default'}, 'id': 'ce5b19a933354bdf87ac6d698494ad47', 'name': 'nfv'}, + 'client_id': 'tacker_api_proj', 'username': 'service-account-tacker_api_proj', 'token_type': 'Bearer', 'active': True} + {{(pid=25048) _fetch_token /opt/stack/data/venv/lib/python3.10/site-packages/keystonemiddleware/external_oauth2_token.py:731}} -About OpenStack Command ------------------------ +Using Tacker API +---------------- When using an external OAuth 2.0 authorization server, the current version of OpenStack Command is not supported. +Cleaning Up +----------- + +When the testing Keycloak environment is no longer is needed as the testing had +finished, Keycloak docker container can be removed by simply running the +following command. + +.. code-block:: console + + $ docker stop keycloak && docker rm keycloak + + .. _RFC6749: https://datatracker.ietf.org/doc/html/rfc6749 .. _Keycloak: https://www.keycloak.org/ .. _NFV-SOL013 v3.4.1: https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/013/03.04.01_60/gs_nfv-sol013v030401p.pdf .. _Middleware Architecture: https://docs.openstack.org/keystonemiddleware/latest/middlewarearchitecture.html +.. _openid-connect 1.0 core specs: https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication +.. _RFC7523: https://www.rfc-editor.org/rfc/rfc7523#section-3.2 +.. _RFC7519: https://www.rfc-editor.org/rfc/rfc7519 +.. _project details: https://docs.openstack.org/keystone/latest/admin/cli-manage-projects-users-and-roles.html +.. _domain details: https://docs.openstack.org/security-guide/identity/domains.html +.. _Mappers tab of Client scope page in the Keycloak dashboard: https://www.keycloak.org/docs/latest/server_admin/#protocol diff --git a/doc/tools/ext_oauth2_server/base_realm.json b/doc/tools/ext_oauth2_server/base_realm.json new file mode 100644 index 000000000..61387d383 --- /dev/null +++ b/doc/tools/ext_oauth2_server/base_realm.json @@ -0,0 +1,2942 @@ +{ + "id": "44b4bbe6-a822-432f-b825-5838f9f3c246", + "realm": "testrealm", + "displayName": "", + "displayNameHtml": "", + "notBefore": 0, + "defaultSignatureAlgorithm": "RS256", + "revokeRefreshToken": false, + "refreshTokenMaxReuse": 0, + "accessTokenLifespan": 300, + "accessTokenLifespanForImplicitFlow": 900, + "ssoSessionIdleTimeout": 1800, + "ssoSessionMaxLifespan": 36000, + "ssoSessionIdleTimeoutRememberMe": 0, + "ssoSessionMaxLifespanRememberMe": 0, + "offlineSessionIdleTimeout": 2592000, + "offlineSessionMaxLifespanEnabled": false, + "offlineSessionMaxLifespan": 5184000, + "clientSessionIdleTimeout": 0, + "clientSessionMaxLifespan": 0, + "clientOfflineSessionIdleTimeout": 0, + "clientOfflineSessionMaxLifespan": 0, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "accessCodeLifespanLogin": 1800, + "actionTokenGeneratedByAdminLifespan": 43200, + "actionTokenGeneratedByUserLifespan": 300, + "oauth2DeviceCodeLifespan": 600, + "oauth2DevicePollingInterval": 5, + "enabled": true, + "sslRequired": "none", + "registrationAllowed": false, + "registrationEmailAsUsername": false, + "rememberMe": false, + "verifyEmail": false, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "editUsernameAllowed": false, + "bruteForceProtected": false, + "permanentLockout": false, + "maxTemporaryLockouts": 0, + "maxFailureWaitSeconds": 900, + "minimumQuickLoginWaitSeconds": 60, + "waitIncrementSeconds": 60, + "quickLoginCheckMilliSeconds": 1000, + "maxDeltaTimeSeconds": 43200, + "failureFactor": 30, + "roles": { + "realm": [ + { + "id": "edcdfc8a-71ee-4db8-b262-bb2fa42aa3b1", + "name": "default-roles-testrealm", + "description": "${role_default-roles}", + "composite": true, + "composites": { + "realm": [ + "offline_access", + "uma_authorization" + ], + "client": { + "account": [ + "manage-account", + "view-profile" + ] + } + }, + "clientRole": false, + "containerId": "44b4bbe6-a822-432f-b825-5838f9f3c246", + "attributes": {} + }, + { + "id": "4bff5ff0-19a9-4cf5-92ff-a7d195842ae5", + "name": "offline_access", + "description": "${role_offline-access}", + "composite": false, + "clientRole": false, + "containerId": "44b4bbe6-a822-432f-b825-5838f9f3c246", + "attributes": {} + }, + { + "id": "5905cff2-83ee-4e38-a4a3-a2ef0ebbbe8c", + "name": "admin", + "description": "", + "composite": false, + "clientRole": false, + "containerId": "44b4bbe6-a822-432f-b825-5838f9f3c246", + "attributes": {} + }, + { + "id": "cec1c865-9357-44c1-bd16-125bd6b2f4e7", + "name": "uma_authorization", + "description": "${role_uma_authorization}", + "composite": false, + "clientRole": false, + "containerId": "44b4bbe6-a822-432f-b825-5838f9f3c246", + "attributes": {} + } + ], + "client": { + "realm-management": [ + { + "id": "01b89d6a-90d4-4744-8806-bb8d65efc9e7", + "name": "manage-events", + "description": "${role_manage-events}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "0cc1cb17-bfc5-4cc8-b3a0-982625f666d8", + "name": "view-clients", + "description": "${role_view-clients}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-clients" + ] + } + }, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "34c7540f-7e05-4d7e-b119-885f86e637f8", + "name": "manage-authorization", + "description": "${role_manage-authorization}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "0be17488-62f9-46ec-8a5d-b6d4b6ccef00", + "name": "manage-clients", + "description": "${role_manage-clients}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "b330d35d-75e3-4cb9-b8ae-b68ce7687348", + "name": "view-events", + "description": "${role_view-events}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "d463b813-5aa0-4b37-b924-b2d43bd02e47", + "name": "manage-users", + "description": "${role_manage-users}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "1ea2450c-404f-4f62-875d-31cb50415c23", + "name": "realm-admin", + "description": "${role_realm-admin}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "manage-events", + "view-clients", + "manage-authorization", + "manage-clients", + "view-events", + "manage-users", + "query-groups", + "query-users", + "impersonation", + "view-authorization", + "view-users", + "query-clients", + "manage-realm", + "manage-identity-providers", + "create-client", + "view-realm", + "view-identity-providers", + "query-realms" + ] + } + }, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "1345a32e-9b48-4e79-b5d5-92fba064f9d7", + "name": "query-groups", + "description": "${role_query-groups}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "a376d371-e820-4969-90e2-d58599ef222b", + "name": "query-users", + "description": "${role_query-users}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "5085779f-33a2-4554-bfad-a1ce177fa8ce", + "name": "impersonation", + "description": "${role_impersonation}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "71d8f2a5-2f4d-4e61-8c16-80e188fab529", + "name": "view-authorization", + "description": "${role_view-authorization}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "b84df183-64a2-490c-98d0-755c3b85f563", + "name": "view-users", + "description": "${role_view-users}", + "composite": true, + "composites": { + "client": { + "realm-management": [ + "query-groups", + "query-users" + ] + } + }, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "5f9cade7-44ff-44d9-be1c-9a8cf7d5d1c1", + "name": "query-clients", + "description": "${role_query-clients}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "132028b9-3b0c-4e73-b14e-4828b26c663d", + "name": "manage-realm", + "description": "${role_manage-realm}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "949f2571-9ada-449c-a88f-f50a288c1a49", + "name": "create-client", + "description": "${role_create-client}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "6dcd437d-7224-49fa-bb8b-5ffcdf5e7e02", + "name": "manage-identity-providers", + "description": "${role_manage-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "010bbfc0-8f18-4c6b-8ec3-36c4386e9fc2", + "name": "view-realm", + "description": "${role_view-realm}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "dec6afea-9269-4fe4-a888-5e66b14c8118", + "name": "query-realms", + "description": "${role_query-realms}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + }, + { + "id": "2374ff32-5670-4cf9-b67d-cb055330469a", + "name": "view-identity-providers", + "description": "${role_view-identity-providers}", + "composite": false, + "clientRole": true, + "containerId": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "attributes": {} + } + ], + "tacker_api_proj": [], + "security-admin-console": [], + "admin-cli": [], + "account-console": [], + "broker": [ + { + "id": "95c79a30-a5cf-4fd7-b2b6-d2ab76879767", + "name": "read-token", + "description": "${role_read-token}", + "composite": false, + "clientRole": true, + "containerId": "03b74bae-627f-44de-8cb8-1b388e240ae5", + "attributes": {} + } + ], + "tacker_api_domain": [], + "tacker_service": [ + { + "id": "4c205264-0742-4478-88fc-f545862dff72", + "name": "uma_protection", + "composite": false, + "clientRole": true, + "containerId": "6dcee2a0-e8ff-44b3-ab1a-889ca0ea0268", + "attributes": {} + }, + { + "id": "ea94f555-7205-43cd-bdf1-079984ff72fc", + "name": "admin", + "description": "", + "composite": false, + "clientRole": true, + "containerId": "6dcee2a0-e8ff-44b3-ab1a-889ca0ea0268", + "attributes": {} + } + ], + "account": [ + { + "id": "8655e721-9e9e-41ed-828a-559e1ab6ee01", + "name": "view-applications", + "description": "${role_view-applications}", + "composite": false, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "59ae436f-6f73-463c-b8e7-04a3585ec67a", + "name": "manage-account-links", + "description": "${role_manage-account-links}", + "composite": false, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "55a94fe1-2f7c-44a2-88e1-81eccab2c6c3", + "name": "manage-account", + "description": "${role_manage-account}", + "composite": true, + "composites": { + "client": { + "account": [ + "manage-account-links" + ] + } + }, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "3862c24f-e75f-4a65-89bf-2e4bc507c051", + "name": "view-groups", + "description": "${role_view-groups}", + "composite": false, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "53461700-1d4e-40af-90a6-3d8fb821653d", + "name": "view-profile", + "description": "${role_view-profile}", + "composite": false, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "b7ff7acb-955d-46c1-9cfc-f4d2b4454f27", + "name": "delete-account", + "description": "${role_delete-account}", + "composite": false, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "34aa2bfe-00dd-459c-beb0-bd5e73f20714", + "name": "view-consent", + "description": "${role_view-consent}", + "composite": false, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + }, + { + "id": "749bb1d3-a327-4960-ab3d-fd1bd142995e", + "name": "manage-consent", + "description": "${role_manage-consent}", + "composite": true, + "composites": { + "client": { + "account": [ + "view-consent" + ] + } + }, + "clientRole": true, + "containerId": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "attributes": {} + } + ] + } + }, + "groups": [], + "defaultRole": { + "id": "edcdfc8a-71ee-4db8-b262-bb2fa42aa3b1", + "name": "default-roles-testrealm", + "description": "${role_default-roles}", + "composite": true, + "clientRole": false, + "containerId": "44b4bbe6-a822-432f-b825-5838f9f3c246" + }, + "requiredCredentials": [ + "password" + ], + "otpPolicyType": "totp", + "otpPolicyAlgorithm": "HmacSHA1", + "otpPolicyInitialCounter": 0, + "otpPolicyDigits": 6, + "otpPolicyLookAheadWindow": 1, + "otpPolicyPeriod": 30, + "otpPolicyCodeReusable": false, + "otpSupportedApplications": [ + "totpAppFreeOTPName", + "totpAppGoogleName", + "totpAppMicrosoftAuthenticatorName" + ], + "localizationTexts": {}, + "webAuthnPolicyRpEntityName": "keycloak", + "webAuthnPolicySignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyRpId": "", + "webAuthnPolicyAttestationConveyancePreference": "not specified", + "webAuthnPolicyAuthenticatorAttachment": "not specified", + "webAuthnPolicyRequireResidentKey": "not specified", + "webAuthnPolicyUserVerificationRequirement": "not specified", + "webAuthnPolicyCreateTimeout": 0, + "webAuthnPolicyAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyAcceptableAaguids": [], + "webAuthnPolicyExtraOrigins": [], + "webAuthnPolicyPasswordlessRpEntityName": "keycloak", + "webAuthnPolicyPasswordlessSignatureAlgorithms": [ + "ES256" + ], + "webAuthnPolicyPasswordlessRpId": "", + "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", + "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", + "webAuthnPolicyPasswordlessRequireResidentKey": "not specified", + "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified", + "webAuthnPolicyPasswordlessCreateTimeout": 0, + "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false, + "webAuthnPolicyPasswordlessAcceptableAaguids": [], + "webAuthnPolicyPasswordlessExtraOrigins": [], + "users": [ + { + "id": "f38feae6-ecb4-45e1-b4e1-efd9e6695519", + "username": "service-account-tacker_api_domain", + "emailVerified": false, + "createdTimestamp": 1733301279638, + "enabled": true, + "totp": false, + "serviceAccountClientId": "tacker_api_domain", + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-testrealm" + ], + "notBefore": 0, + "groups": [] + }, + { + "id": "7d3e5929-4bbe-4ef4-90e3-8fd4b445ed7f", + "username": "service-account-tacker_api_proj", + "emailVerified": false, + "createdTimestamp": 1733301507102, + "enabled": true, + "totp": false, + "serviceAccountClientId": "tacker_api_proj", + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-testrealm" + ], + "notBefore": 0, + "groups": [] + }, + { + "id": "7e3c5cb5-48a4-460c-b206-b8dca2ea0c36", + "username": "service-account-tacker_service", + "emailVerified": false, + "createdTimestamp": 1722498277399, + "enabled": true, + "totp": false, + "serviceAccountClientId": "tacker_service", + "disableableCredentialTypes": [], + "requiredActions": [], + "realmRoles": [ + "default-roles-testrealm" + ], + "clientRoles": { + "tacker_service": [ + "uma_protection" + ] + }, + "notBefore": 0, + "groups": [] + } + ], + "scopeMappings": [ + { + "clientScope": "offline_access", + "roles": [ + "offline_access" + ] + } + ], + "clientScopeMappings": { + "account": [ + { + "client": "account-console", + "roles": [ + "manage-account", + "view-groups" + ] + } + ] + }, + "clients": [ + { + "id": "db0a44c3-bfde-4736-9e4c-e696dd71d81e", + "clientId": "account", + "name": "${client_account}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/testrealm/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/testrealm/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "6f285005-5f82-42c7-b278-02169fd5c433", + "clientId": "account-console", + "name": "${client_account-console}", + "rootUrl": "${authBaseUrl}", + "baseUrl": "/realms/testrealm/account/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/realms/testrealm/account/*" + ], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "33d5154d-19d3-4f82-a0ce-656838ca05c2", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": {} + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "49da92cd-0d21-4d65-b908-14c662c31938", + "clientId": "admin-cli", + "name": "${client_admin-cli}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": false, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "03b74bae-627f-44de-8cb8-1b388e240ae5", + "clientId": "broker", + "name": "${client_broker}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "b26aae5d-2550-4902-a0d3-0dadc304003d", + "clientId": "realm-management", + "name": "${client_realm-management}", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [], + "webOrigins": [], + "notBefore": 0, + "bearerOnly": true, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": false, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "true", + "post.logout.redirect.uris": "+" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": false, + "nodeReRegistrationTimeout": 0, + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "a0f4d473-b850-439f-b276-ff87bd98f238", + "clientId": "security-admin-console", + "name": "${client_security-admin-console}", + "rootUrl": "${authAdminUrl}", + "baseUrl": "/admin/testrealm/console/", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client-secret", + "redirectUris": [ + "/admin/testrealm/console/*" + ], + "webOrigins": [ + "+" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": false, + "directAccessGrantsEnabled": false, + "serviceAccountsEnabled": false, + "publicClient": true, + "frontchannelLogout": false, + "protocol": "openid-connect", + "attributes": { + "realm_client": "false", + "client.use.lightweight.access.token.enabled": "true", + "post.logout.redirect.uris": "+", + "pkce.code.challenge.method": "S256" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": 0, + "protocolMappers": [ + { + "id": "099cc32a-a075-4e28-90d6-e19c955c3cdf", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "20e42f2e-d758-4a77-9ca9-862507689c52", + "clientId": "tacker_api_domain", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client_credential_grant_flow_type", + "secret": "iIK6lARLzJgoQQyMyoymNYrGTDuR0733S", + "redirectUris": [ + "/*" + ], + "webOrigins": [ + "/*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "client.secret.creation.time": "1725858431", + "x509.subjectdn": "(.?)CN(.*)=(.*)(.?)(?:$)", + "client.introspection.response.allow.jwt.claim.enabled": "false", + "post.logout.redirect.uris": "+", + "oauth2.device.authorization.grant.enabled": "true", + "use.jwks.url": "true", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "jwt.credential.certificate": "os_public_cert_string", + "realm_client": "false", + "oidc.ciba.grant.enabled": "true", + "client.use.lightweight.access.token.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "tls.client.certificate.bound.access.tokens": "false", + "require.pushed.authorization.requests": "false", + "acr.loa.map": "{}", + "display.on.consent.screen": "false", + "x509.allow.regex.pattern.comparison": "true", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "95cf1350-8dba-4eb4-b9dc-2c73540c6408", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "19e22a4e-e658-48ca-83f5-1ffa84783466", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "cdfcb3a6-3e64-49d6-9fb2-b45d0b9a2d12", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "client_id", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "client_id", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "domain_scope", + "acr", + "tacker_scope", + "profile", + "roles", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "9b32fc96-8637-4143-aa8a-4bda24fcfa4c", + "clientId": "tacker_api_proj", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client_credential_grant_flow_type", + "secret": "iIK6lARLzJgoQQyMyoymNYrGTDuR0733S", + "redirectUris": [ + "/*" + ], + "webOrigins": [ + "/*" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "client.secret.creation.time": "1725858431", + "x509.subjectdn": "(.?)CN(.*)=(.*)(.?)(?:$)", + "client.introspection.response.allow.jwt.claim.enabled": "false", + "post.logout.redirect.uris": "+", + "oauth2.device.authorization.grant.enabled": "true", + "use.jwks.url": "true", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "jwt.credential.certificate": "os_public_cert_string", + "realm_client": "false", + "oidc.ciba.grant.enabled": "true", + "client.use.lightweight.access.token.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "tls.client.certificate.bound.access.tokens": "false", + "require.pushed.authorization.requests": "false", + "acr.loa.map": "{}", + "display.on.consent.screen": "false", + "x509.allow.regex.pattern.comparison": "true", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "31423cb2-c0d0-4cf5-a183-e159b89f4e86", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + }, + { + "id": "c99c65fb-c97f-4937-b512-f179e63f2e40", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "client_id", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "client_id", + "jsonType.label": "String" + } + }, + { + "id": "cb2323fb-eabc-497a-98aa-9cf3a3cb6821", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "tacker_scope", + "profile", + "roles", + "project_scope", + "basic", + "email" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "microprofile-jwt" + ] + }, + { + "id": "6dcee2a0-e8ff-44b3-ab1a-889ca0ea0268", + "clientId": "tacker_service", + "name": "", + "description": "", + "rootUrl": "", + "adminUrl": "", + "baseUrl": "", + "surrogateAuthRequired": false, + "enabled": true, + "alwaysDisplayInConsole": false, + "clientAuthenticatorType": "client_credential_grant_flow_type", + "secret": "iIK6lARLzJgoQQyMyoymNYrGTDuR0733S", + "redirectUris": [ + "http://127.0.0.1:9890/*" + ], + "webOrigins": [ + "https://127.0.0.1:9890/" + ], + "notBefore": 0, + "bearerOnly": false, + "consentRequired": false, + "standardFlowEnabled": true, + "implicitFlowEnabled": true, + "directAccessGrantsEnabled": true, + "serviceAccountsEnabled": true, + "publicClient": false, + "frontchannelLogout": true, + "protocol": "openid-connect", + "attributes": { + "client.secret.creation.time": "1725858431", + "x509.subjectdn": "(.?)CN(.*)=(.*)(.?)(?:$)", + "client.introspection.response.allow.jwt.claim.enabled": "false", + "post.logout.redirect.uris": "+", + "oauth2.device.authorization.grant.enabled": "true", + "use.jwks.url": "true", + "backchannel.logout.revoke.offline.tokens": "false", + "use.refresh.tokens": "true", + "jwt.credential.certificate": "os_public_cert_string", + "realm_client": "false", + "oidc.ciba.grant.enabled": "true", + "client.use.lightweight.access.token.enabled": "false", + "backchannel.logout.session.required": "true", + "client_credentials.use_refresh_token": "false", + "tls.client.certificate.bound.access.tokens": "false", + "require.pushed.authorization.requests": "false", + "acr.loa.map": "{}", + "display.on.consent.screen": "false", + "x509.allow.regex.pattern.comparison": "true", + "token.response.type.bearer.lower-case": "false" + }, + "authenticationFlowBindingOverrides": {}, + "fullScopeAllowed": true, + "nodeReRegistrationTimeout": -1, + "protocolMappers": [ + { + "id": "aefdf776-660b-4054-b065-784557b882e4", + "name": "sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-sub-mapper", + "consentRequired": false, + "config": { + "lightweight.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "aaf03228-bbdf-4f7d-a899-1fe9eabd069c", + "name": "Client Host", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientHost", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientHost", + "jsonType.label": "String" + } + }, + { + "id": "a9a70f9c-94de-49da-af50-1f2015b26920", + "name": "Client ID", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "client_id", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "client_id", + "jsonType.label": "String" + } + }, + { + "id": "50a49756-111d-45bb-af75-6b1e934bb83a", + "name": "Client IP Address", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "clientAddress", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "clientAddress", + "jsonType.label": "String" + } + } + ], + "defaultClientScopes": [ + "web-origins", + "acr", + "tacker_scope", + "roles", + "basic" + ], + "optionalClientScopes": [ + "address", + "phone", + "offline_access", + "profile", + "microprofile-jwt", + "email" + ] + } + ], + "clientScopes": [ + { + "id": "3fb399ad-588a-4d96-bfbd-56239ddfc190", + "name": "acr", + "description": "OpenID Connect scope for add acr (authentication context class reference) to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "f771232b-14fa-41ea-8beb-d654e0504107", + "name": "acr loa level", + "protocol": "openid-connect", + "protocolMapper": "oidc-acr-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + } + ] + }, + { + "id": "f75d05d0-3419-43ce-8009-a60dbda7ba5e", + "name": "basic", + "description": "OpenID Connect scope for add all basic claims to the token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "0bbe22de-2ceb-4d66-bf8f-250a3c51da55", + "name": "sub", + "protocol": "openid-connect", + "protocolMapper": "oidc-sub-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + }, + { + "id": "90049a57-0fad-4fa4-b612-685089f1b425", + "name": "auth_time", + "protocol": "openid-connect", + "protocolMapper": "oidc-usersessionmodel-note-mapper", + "consentRequired": false, + "config": { + "user.session.note": "AUTH_TIME", + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "auth_time", + "jsonType.label": "long" + } + } + ] + }, + { + "id": "a0c55b58-69e5-4b0b-ade2-3fdf482e809d", + "name": "role_list", + "description": "SAML role list", + "protocol": "saml", + "attributes": { + "consent.screen.text": "${samlRoleListScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "9b50cfdb-d0eb-43ab-8d95-56c89b93bc08", + "name": "role list", + "protocol": "saml", + "protocolMapper": "saml-role-list-mapper", + "consentRequired": false, + "config": { + "single": "false", + "attribute.nameformat": "Basic", + "attribute.name": "Role" + } + } + ] + }, + { + "id": "b8ce1300-3d8d-498d-805f-d349a1f4fe3b", + "name": "roles", + "description": "OpenID Connect scope for add user roles to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "${rolesScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "08e42628-19c0-4cfb-a5d3-0df60390ddeb", + "name": "realm roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "realm_access.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "8068a6b5-b9d8-4f3e-8a64-3c13c04c9367", + "name": "client roles", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-client-role-mapper", + "consentRequired": false, + "config": { + "user.attribute": "foo", + "introspection.token.claim": "true", + "access.token.claim": "true", + "claim.name": "resource_access.${client_id}.roles", + "jsonType.label": "String", + "multivalued": "true" + } + }, + { + "id": "6a2c2e3c-de78-4e00-b73b-58219683d514", + "name": "audience resolve", + "protocol": "openid-connect", + "protocolMapper": "oidc-audience-resolve-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "b72605a2-a3c7-4e53-ace6-350f266734df", + "name": "tacker_scope", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "5a47e9a3-b010-472a-87ce-c13334a93722", + "name": "tacker_user", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "claim.value": "{\"domain\": { \"name\": \"os_tacker_user_domain_name\", \"id\": \"os_tacker_user_domain_id\"},\"name\": \"os_tacker_username\", \"id\": \"os_tacker_user_id\"},", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "user", + "jsonType.label": "JSON", + "access.tokenResponse.claim": "false" + } + } + ] + }, + { + "id": "0a3b19ed-ccf6-4890-b7ba-97cc913d1809", + "name": "web-origins", + "description": "OpenID Connect scope for add allowed web origins to the access token", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "consent.screen.text": "", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "765367da-bff2-4649-88b9-63c32b074d6c", + "name": "allowed web origins", + "protocol": "openid-connect", + "protocolMapper": "oidc-allowed-origins-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "access.token.claim": "true" + } + } + ] + }, + { + "id": "2c0f7ed6-db6d-4fe1-90bc-77b9b8e1a3a5", + "name": "email", + "description": "OpenID Connect built-in scope: email", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${emailScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "0ad844ef-4ffa-4977-a3c3-a31041df8e49", + "name": "email", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "email", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email", + "jsonType.label": "String" + } + }, + { + "id": "d9d26ad0-e045-46ac-af6d-a645842c6f9c", + "name": "email verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-property-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "emailVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "email_verified", + "jsonType.label": "boolean" + } + } + ] + }, + { + "id": "f28ec368-f7c3-42e2-a301-7373c0d324a3", + "name": "offline_access", + "description": "OpenID Connect built-in scope: offline_access", + "protocol": "openid-connect", + "attributes": { + "consent.screen.text": "${offlineAccessScopeConsentText}", + "display.on.consent.screen": "true" + } + }, + { + "id": "2dc37cd2-0603-43e3-a71a-b370396a5c46", + "name": "address", + "description": "OpenID Connect built-in scope: address", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${addressScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "0b0f871e-eb84-4cd3-ab73-10216ed47a58", + "name": "address", + "protocol": "openid-connect", + "protocolMapper": "oidc-address-mapper", + "consentRequired": false, + "config": { + "user.attribute.formatted": "formatted", + "user.attribute.country": "country", + "introspection.token.claim": "true", + "user.attribute.postal_code": "postal_code", + "userinfo.token.claim": "true", + "user.attribute.street": "street", + "id.token.claim": "true", + "user.attribute.region": "region", + "access.token.claim": "true", + "user.attribute.locality": "locality" + } + } + ] + }, + { + "id": "157145c3-99f2-4255-a310-3def6c7b91b2", + "name": "project_scope", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "33ef3c0f-3f5d-4296-b521-2e0a9793b951", + "name": "tacker_project_info", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "claim.value": "{\"domain\": {\"id\": \"os_tacker_project_domain_id\", \"name\": \"os_tacker_project_domain_name\"},\"id\": \"os_tacker_project_id\", \"name\": \"os_tacker_project_name\"}", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "project_info", + "jsonType.label": "JSON", + "access.tokenResponse.claim": "false" + } + }, + { + "id": "aa7056c7-55f2-44d7-8399-e9051fe427c3", + "name": "tacker_role_info", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "claim.value": "os_tacker_roles", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "role_info", + "jsonType.label": "String", + "access.tokenResponse.claim": "false" + } + } + ] + }, + { + "id": "db7e3eeb-3434-4339-aff7-9c352d521abf", + "name": "microprofile-jwt", + "description": "Microprofile - JWT built-in scope", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "display.on.consent.screen": "false" + }, + "protocolMappers": [ + { + "id": "a9c0654b-3684-444f-bd3b-ff323b4eb8a8", + "name": "upn", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "upn", + "jsonType.label": "String" + } + }, + { + "id": "19236eab-108e-41ce-aea6-8fb4902b2163", + "name": "groups", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-realm-role-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "multivalued": "true", + "userinfo.token.claim": "true", + "user.attribute": "foo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "groups", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "7019ae1e-412c-4e49-bfce-ee4965c4551d", + "name": "domain_scope", + "description": "", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "false", + "display.on.consent.screen": "true", + "gui.order": "", + "consent.screen.text": "" + }, + "protocolMappers": [ + { + "id": "66509ec4-6bbb-4f7c-b526-5047c434aa6c", + "name": "tacker_role_info", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "claim.value": "os_tacker_roles", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "role_info", + "jsonType.label": "String", + "access.tokenResponse.claim": "false" + } + }, + { + "id": "a2a82cd9-834a-4a10-bb84-7b3610f81e42", + "name": "tacker_project_info", + "protocol": "openid-connect", + "protocolMapper": "oidc-hardcoded-claim-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "claim.value": "{\"domain\": {\"id\": \"os_tacker_project_domain_id\", \"name\": \"os_tacker_project_domain_name\"}}", + "userinfo.token.claim": "true", + "id.token.claim": "true", + "lightweight.claim": "false", + "access.token.claim": "true", + "claim.name": "project_info", + "jsonType.label": "JSON", + "access.tokenResponse.claim": "false" + } + } + ] + }, + { + "id": "f0f33e28-b14c-4bda-b1c5-778fd5b6b0fe", + "name": "profile", + "description": "OpenID Connect built-in scope: profile", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${profileScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "dd5c8121-a8c3-4102-8772-c2aa10d8c0fd", + "name": "nickname", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "nickname", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "nickname", + "jsonType.label": "String" + } + }, + { + "id": "ba30d1ed-2d77-4183-b15f-945f6a5d0a3d", + "name": "website", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "website", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "website", + "jsonType.label": "String" + } + }, + { + "id": "1abc5411-c0d1-429c-aac9-99e43b18051b", + "name": "profile", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "profile", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "profile", + "jsonType.label": "String" + } + }, + { + "id": "66b8c97f-1542-4c6b-830c-1f3741d866bb", + "name": "full name", + "protocol": "openid-connect", + "protocolMapper": "oidc-full-name-mapper", + "consentRequired": false, + "config": { + "id.token.claim": "true", + "introspection.token.claim": "true", + "access.token.claim": "true", + "userinfo.token.claim": "true" + } + }, + { + "id": "3f7196c5-8f94-482d-a5c9-23244d93389e", + "name": "given name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "firstName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "given_name", + "jsonType.label": "String" + } + }, + { + "id": "f016af8b-46ae-47ab-8ba7-c3c5b7242d53", + "name": "updated at", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "updatedAt", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "updated_at", + "jsonType.label": "long" + } + }, + { + "id": "f337a750-b4f7-4e84-af1f-53e2e369a990", + "name": "picture", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "picture", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "picture", + "jsonType.label": "String" + } + }, + { + "id": "13043a02-bf23-49a3-b9f1-09147803234a", + "name": "family name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "lastName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "family_name", + "jsonType.label": "String" + } + }, + { + "id": "677d960f-e102-42c2-80c9-d54102cd11a2", + "name": "middle name", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "middleName", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "middle_name", + "jsonType.label": "String" + } + }, + { + "id": "ee01fb1d-7e6a-45a8-bdb9-e1d7e4f16a80", + "name": "gender", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "gender", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "gender", + "jsonType.label": "String" + } + }, + { + "id": "4c095e73-3e3f-46b4-8d89-f717a4805b8d", + "name": "locale", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "locale", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "locale", + "jsonType.label": "String" + } + }, + { + "id": "dbccd41f-69b3-4e8e-9ac9-41566e5b60e5", + "name": "zoneinfo", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "zoneinfo", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "zoneinfo", + "jsonType.label": "String" + } + }, + { + "id": "0243824b-4109-4527-84a8-35303e07e541", + "name": "birthdate", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "birthdate", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "birthdate", + "jsonType.label": "String" + } + }, + { + "id": "64d14caa-9ca2-4bcc-adc8-1f9562b8766e", + "name": "username", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "username", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "preferred_username", + "jsonType.label": "String" + } + } + ] + }, + { + "id": "9df1ea7e-d0e5-4217-b645-f4b5b652f148", + "name": "phone", + "description": "OpenID Connect built-in scope: phone", + "protocol": "openid-connect", + "attributes": { + "include.in.token.scope": "true", + "consent.screen.text": "${phoneScopeConsentText}", + "display.on.consent.screen": "true" + }, + "protocolMappers": [ + { + "id": "81c5fd52-3e5a-4471-be42-a895ee0d97e6", + "name": "phone number verified", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumberVerified", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number_verified", + "jsonType.label": "boolean" + } + }, + { + "id": "df965874-1ab7-4d49-beee-b8efb5bded3d", + "name": "phone number", + "protocol": "openid-connect", + "protocolMapper": "oidc-usermodel-attribute-mapper", + "consentRequired": false, + "config": { + "introspection.token.claim": "true", + "userinfo.token.claim": "true", + "user.attribute": "phoneNumber", + "id.token.claim": "true", + "access.token.claim": "true", + "claim.name": "phone_number", + "jsonType.label": "String" + } + } + ] + } + ], + "defaultDefaultClientScopes": [ + "role_list", + "profile", + "email", + "roles", + "web-origins", + "acr", + "basic", + "tacker_scope" + ], + "defaultOptionalClientScopes": [ + "offline_access", + "address", + "phone", + "microprofile-jwt" + ], + "browserSecurityHeaders": { + "contentSecurityPolicyReportOnly": "", + "xContentTypeOptions": "nosniff", + "referrerPolicy": "no-referrer", + "xRobotsTag": "none", + "xFrameOptions": "SAMEORIGIN", + "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';", + "xXSSProtection": "1; mode=block", + "strictTransportSecurity": "max-age=31536000; includeSubDomains" + }, + "smtpServer": {}, + "eventsEnabled": true, + "eventsExpiration": 360, + "eventsListeners": [ + "jboss-logging", + "email" + ], + "enabledEventTypes": [ + "UPDATE_CONSENT_ERROR", + "UPDATE_TOTP", + "PERMISSION_TOKEN_ERROR", + "IDENTITY_PROVIDER_RETRIEVE_TOKEN_ERROR", + "IMPERSONATE_ERROR", + "CUSTOM_REQUIRED_ACTION", + "RESTART_AUTHENTICATION", + "CLIENT_INFO", + "IMPERSONATE", + "LOGIN", + "CLIENT_INITIATED_ACCOUNT_LINKING", + "OAUTH2_EXTENSION_GRANT", + "USER_DISABLED_BY_PERMANENT_LOCKOUT", + "USER_DISABLED_BY_TEMPORARY_LOCKOUT_ERROR", + "TOKEN_EXCHANGE", + "REGISTER", + "DELETE_ACCOUNT_ERROR", + "IDENTITY_PROVIDER_LINK_ACCOUNT", + "INTROSPECT_TOKEN_ERROR", + "USER_DISABLED_BY_TEMPORARY_LOCKOUT", + "DELETE_ACCOUNT", + "UPDATE_PASSWORD", + "IDENTITY_PROVIDER_FIRST_LOGIN", + "VERIFY_EMAIL", + "CLIENT_LOGIN_ERROR", + "RESTART_AUTHENTICATION_ERROR", + "EXECUTE_ACTIONS", + "REMOVE_FEDERATED_IDENTITY_ERROR", + "TOKEN_EXCHANGE_ERROR", + "UNREGISTER_NODE", + "FEDERATED_IDENTITY_OVERRIDE_LINK", + "SEND_IDENTITY_PROVIDER_LINK_ERROR", + "USER_INFO_REQUEST_ERROR", + "EXECUTE_ACTION_TOKEN_ERROR", + "OAUTH2_EXTENSION_GRANT_ERROR", + "SEND_VERIFY_EMAIL", + "IDENTITY_PROVIDER_RESPONSE", + "EXECUTE_ACTIONS_ERROR", + "IDENTITY_PROVIDER_RETRIEVE_TOKEN", + "OAUTH2_DEVICE_CODE_TO_TOKEN", + "USER_DISABLED_BY_PERMANENT_LOCKOUT_ERROR", + "UNREGISTER_NODE_ERROR", + "VALIDATE_ACCESS_TOKEN_ERROR", + "OAUTH2_DEVICE_VERIFY_USER_CODE_ERROR", + "REVOKE_GRANT_ERROR", + "UPDATE_EMAIL_ERROR", + "INVITE_ORG_ERROR", + "UPDATE_PROFILE", + "USER_INFO_REQUEST", + "SEND_IDENTITY_PROVIDER_LINK", + "SEND_VERIFY_EMAIL_ERROR", + "CLIENT_INITIATED_ACCOUNT_LINKING_ERROR", + "OAUTH2_DEVICE_AUTH_ERROR", + "REMOVE_TOTP_ERROR", + "VERIFY_EMAIL_ERROR", + "CLIENT_UPDATE", + "UPDATE_TOTP_ERROR", + "VERIFY_PROFILE", + "GRANT_CONSENT_ERROR", + "SEND_RESET_PASSWORD", + "GRANT_CONSENT", + "REGISTER_NODE_ERROR", + "VERIFY_PROFILE_ERROR", + "REMOVE_TOTP", + "REVOKE_GRANT", + "LOGIN_ERROR", + "CLIENT_LOGIN", + "RESET_PASSWORD_ERROR", + "CODE_TO_TOKEN_ERROR", + "OAUTH2_DEVICE_CODE_TO_TOKEN_ERROR", + "UPDATE_PROFILE_ERROR", + "VALIDATE_ACCESS_TOKEN", + "OAUTH2_DEVICE_VERIFY_USER_CODE", + "UPDATE_PASSWORD_ERROR", + "IDENTITY_PROVIDER_LOGIN", + "AUTHREQID_TO_TOKEN", + "LOGOUT", + "CLIENT_INFO_ERROR", + "CLIENT_REGISTER", + "PUSHED_AUTHORIZATION_REQUEST", + "REFRESH_TOKEN", + "INTROSPECT_TOKEN", + "CLIENT_DELETE", + "FEDERATED_IDENTITY_LINK_ERROR", + "CLIENT_DELETE_ERROR", + "PERMISSION_TOKEN", + "REGISTER_NODE", + "INVALID_SIGNATURE", + "PUSHED_AUTHORIZATION_REQUEST_ERROR", + "OAUTH2_DEVICE_AUTH", + "REMOVE_FEDERATED_IDENTITY", + "IDENTITY_PROVIDER_POST_LOGIN", + "IDENTITY_PROVIDER_LINK_ACCOUNT_ERROR", + "FEDERATED_IDENTITY_OVERRIDE_LINK_ERROR", + "UPDATE_EMAIL", + "REGISTER_ERROR", + "EXECUTE_ACTION_TOKEN", + "LOGOUT_ERROR", + "CLIENT_UPDATE_ERROR", + "AUTHREQID_TO_TOKEN_ERROR", + "INVALID_SIGNATURE_ERROR", + "CLIENT_REGISTER_ERROR", + "FEDERATED_IDENTITY_LINK", + "IDENTITY_PROVIDER_RESPONSE_ERROR", + "INVITE_ORG", + "IDENTITY_PROVIDER_LOGIN_ERROR", + "RESET_PASSWORD", + "UPDATE_CONSENT", + "SEND_RESET_PASSWORD_ERROR", + "REFRESH_TOKEN_ERROR", + "CUSTOM_REQUIRED_ACTION_ERROR", + "IDENTITY_PROVIDER_POST_LOGIN_ERROR", + "CODE_TO_TOKEN", + "IDENTITY_PROVIDER_FIRST_LOGIN_ERROR" + ], + "adminEventsEnabled": true, + "adminEventsDetailsEnabled": true, + "identityProviders": [], + "identityProviderMappers": [], + "components": { + "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [ + { + "id": "65a399d8-d4b7-488d-823f-cc079160a9ab", + "name": "Trusted Hosts", + "providerId": "trusted-hosts", + "subType": "anonymous", + "subComponents": {}, + "config": { + "host-sending-registration-request-must-match": [ + "true" + ], + "client-uris-must-match": [ + "true" + ] + } + }, + { + "id": "92a3bd69-ebb2-4864-8ccc-56df6cb7a85e", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "0bb88c91-b498-4e0b-bcd0-c96d7a11dd27", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "anonymous", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-usermodel-attribute-mapper", + "saml-role-list-mapper", + "oidc-usermodel-property-mapper", + "saml-user-attribute-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-full-name-mapper", + "saml-user-property-mapper", + "oidc-address-mapper" + ] + } + }, + { + "id": "5d899984-6d31-4924-bb3e-5b57a9067fa6", + "name": "Allowed Client Scopes", + "providerId": "allowed-client-templates", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allow-default-scopes": [ + "true" + ] + } + }, + { + "id": "825b577d-bd59-4d5e-bc59-df69350b83a5", + "name": "Max Clients Limit", + "providerId": "max-clients", + "subType": "anonymous", + "subComponents": {}, + "config": { + "max-clients": [ + "200" + ] + } + }, + { + "id": "db289155-5ebc-410f-bac4-0c542c5fe9cb", + "name": "Consent Required", + "providerId": "consent-required", + "subType": "anonymous", + "subComponents": {}, + "config": {} + }, + { + "id": "6c1bace4-ef3c-4421-96b3-c47a9d76003d", + "name": "Allowed Protocol Mapper Types", + "providerId": "allowed-protocol-mappers", + "subType": "authenticated", + "subComponents": {}, + "config": { + "allowed-protocol-mapper-types": [ + "oidc-full-name-mapper", + "oidc-sha256-pairwise-sub-mapper", + "oidc-usermodel-property-mapper", + "saml-user-property-mapper", + "saml-role-list-mapper", + "oidc-address-mapper", + "oidc-usermodel-attribute-mapper", + "saml-user-attribute-mapper" + ] + } + }, + { + "id": "b380de60-8e5e-4cba-8a65-6e8e2612a099", + "name": "Full Scope Disabled", + "providerId": "scope", + "subType": "anonymous", + "subComponents": {}, + "config": {} + } + ], + "org.keycloak.userprofile.UserProfileProvider": [ + { + "id": "c1ec4c16-cdf1-446b-ab71-d5ddeeec5505", + "providerId": "declarative-user-profile", + "subComponents": {}, + "config": { + "kc.user.profile.config": [ + "{\"attributes\":[{\"name\":\"username\",\"displayName\":\"${username}\",\"validations\":{\"length\":{\"min\":3,\"max\":255},\"username-prohibited-characters\":{},\"up-username-not-idn-homograph\":{}},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"email\",\"displayName\":\"${email}\",\"validations\":{\"email\":{},\"length\":{\"max\":255}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"firstName\",\"displayName\":\"${firstName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false},{\"name\":\"lastName\",\"displayName\":\"${lastName}\",\"validations\":{\"length\":{\"max\":255},\"person-name-prohibited-characters\":{}},\"required\":{\"roles\":[\"user\"]},\"permissions\":{\"view\":[\"admin\",\"user\"],\"edit\":[\"admin\",\"user\"]},\"multivalued\":false}],\"groups\":[{\"name\":\"user-metadata\",\"displayHeader\":\"User metadata\",\"displayDescription\":\"Attributes, which refer to user metadata\"}]}" + ] + } + } + ], + "org.keycloak.keys.KeyProvider": [ + { + "id": "72019557-6cc5-46e8-b0a8-209b11b9d2cd", + "name": "hmac-generated-hs512", + "providerId": "hmac-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "HS512" + ] + } + }, + { + "id": "9fbada6b-4fdc-4f9d-ad00-558027c263e1", + "name": "rsa-generated", + "providerId": "rsa-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "5846e48e-75e8-42a5-a2da-1783600b52e3", + "name": "aes-generated", + "providerId": "aes-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ] + } + }, + { + "id": "51661fbc-9b80-4ab0-8cc9-87eb81e53e4f", + "name": "rsa-enc-generated", + "providerId": "rsa-enc-generated", + "subComponents": {}, + "config": { + "priority": [ + "100" + ], + "algorithm": [ + "RSA-OAEP" + ] + } + } + ] + }, + "internationalizationEnabled": false, + "supportedLocales": [], + "authenticationFlows": [ + { + "id": "92525c31-a8e1-4f36-a35f-f6f3315d7482", + "alias": "Account verification options", + "description": "Method with which to verity the existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-email-verification", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Verify Existing Account by Re-authentication", + "userSetupAllowed": false + } + ] + }, + { + "id": "612c487d-a286-4fa5-8f8d-e42f5b3c069c", + "alias": "Browser - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "fea58d30-c2c4-4cbf-bc70-7082adce3063", + "alias": "Direct Grant - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "15d9c0bd-da69-4778-b0f0-3891399616fc", + "alias": "First broker login - Conditional OTP", + "description": "Flow to determine if the OTP is required for the authentication", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-otp-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "1f38b736-f54f-4701-bfe1-00b373297ffe", + "alias": "Handle Existing Account", + "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-confirm-link", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Account verification options", + "userSetupAllowed": false + } + ] + }, + { + "id": "ecd495eb-36a7-4699-88d0-2f9c758a656a", + "alias": "Reset - Conditional OTP", + "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "conditional-user-configured", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-otp", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "10952afb-18df-4340-8f12-83cc408ed9bd", + "alias": "User creation or linking", + "description": "Flow for the existing/non-existing user alternatives", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "create unique user config", + "authenticator": "idp-create-user-if-unique", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Handle Existing Account", + "userSetupAllowed": false + } + ] + }, + { + "id": "0a141d95-f0cd-4945-bd87-fbed8aa86329", + "alias": "Verify Existing Account by Re-authentication", + "description": "Reauthentication of existing account", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "idp-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "First broker login - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "1c7b1e09-bc5e-434e-80cd-c2032165e07c", + "alias": "browser", + "description": "browser based authentication", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-cookie", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "auth-spnego", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "identity-provider-redirector", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 25, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "forms", + "userSetupAllowed": false + } + ] + }, + { + "id": "4a616e5b-0029-4e0e-bfe2-b808f06f892a", + "alias": "clients", + "description": "Base authentication for clients", + "providerId": "client-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "client-secret", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-secret-jwt", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "client-x509", + "authenticatorFlow": false, + "requirement": "ALTERNATIVE", + "priority": 40, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "1086d9f2-c9be-421e-89c6-a149b2ddc595", + "alias": "direct grant", + "description": "OpenID Connect Resource Owner Grant", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "direct-grant-validate-username", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "direct-grant-validate-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 30, + "autheticatorFlow": true, + "flowAlias": "Direct Grant - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "c769e0ce-1948-4352-832e-b54325a88915", + "alias": "docker auth", + "description": "Used by Docker clients to authenticate against the IDP", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "docker-http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "fc96ae89-39cb-4a1c-bb43-30a03a323b26", + "alias": "first broker login", + "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticatorConfig": "review profile config", + "authenticator": "idp-review-profile", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "User creation or linking", + "userSetupAllowed": false + } + ] + }, + { + "id": "57fddbf7-0ae2-4ec3-a890-cc947d4c64de", + "alias": "forms", + "description": "Username, password, otp and other auth forms.", + "providerId": "basic-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "auth-username-password-form", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 20, + "autheticatorFlow": true, + "flowAlias": "Browser - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "9666c9f5-af8b-4b01-aa2b-fd593332f64d", + "alias": "registration", + "description": "registration flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-page-form", + "authenticatorFlow": true, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": true, + "flowAlias": "registration form", + "userSetupAllowed": false + } + ] + }, + { + "id": "e9c12b6e-792a-4070-801e-45ea088b7e29", + "alias": "registration form", + "description": "registration form", + "providerId": "form-flow", + "topLevel": false, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "registration-user-creation", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-password-action", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 50, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-recaptcha-action", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 60, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "registration-terms-and-conditions", + "authenticatorFlow": false, + "requirement": "DISABLED", + "priority": 70, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + }, + { + "id": "4aea517f-7b24-4cda-8109-65a264b4a181", + "alias": "reset credentials", + "description": "Reset credentials for a user if they forgot their password or something", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "reset-credentials-choose-user", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-credential-email", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 20, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticator": "reset-password", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 30, + "autheticatorFlow": false, + "userSetupAllowed": false + }, + { + "authenticatorFlow": true, + "requirement": "CONDITIONAL", + "priority": 40, + "autheticatorFlow": true, + "flowAlias": "Reset - Conditional OTP", + "userSetupAllowed": false + } + ] + }, + { + "id": "b9d8185d-af97-4b45-af89-6f2402e9a258", + "alias": "saml ecp", + "description": "SAML ECP Profile Authentication Flow", + "providerId": "basic-flow", + "topLevel": true, + "builtIn": true, + "authenticationExecutions": [ + { + "authenticator": "http-basic-authenticator", + "authenticatorFlow": false, + "requirement": "REQUIRED", + "priority": 10, + "autheticatorFlow": false, + "userSetupAllowed": false + } + ] + } + ], + "authenticatorConfig": [ + { + "id": "f9489e4a-eb0e-46b8-9bdc-011751ec9dff", + "alias": "create unique user config", + "config": { + "require.password.update.after.registration": "false" + } + }, + { + "id": "0dfc9207-22df-4910-8bc4-9f0610ec9ae1", + "alias": "review profile config", + "config": { + "update.profile.on.first.login": "missing" + } + } + ], + "requiredActions": [ + { + "alias": "CONFIGURE_TOTP", + "name": "Configure OTP", + "providerId": "CONFIGURE_TOTP", + "enabled": true, + "defaultAction": false, + "priority": 10, + "config": {} + }, + { + "alias": "TERMS_AND_CONDITIONS", + "name": "Terms and Conditions", + "providerId": "TERMS_AND_CONDITIONS", + "enabled": false, + "defaultAction": false, + "priority": 20, + "config": {} + }, + { + "alias": "UPDATE_PASSWORD", + "name": "Update Password", + "providerId": "UPDATE_PASSWORD", + "enabled": true, + "defaultAction": false, + "priority": 30, + "config": {} + }, + { + "alias": "UPDATE_PROFILE", + "name": "Update Profile", + "providerId": "UPDATE_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 40, + "config": {} + }, + { + "alias": "VERIFY_EMAIL", + "name": "Verify Email", + "providerId": "VERIFY_EMAIL", + "enabled": true, + "defaultAction": false, + "priority": 50, + "config": {} + }, + { + "alias": "delete_account", + "name": "Delete Account", + "providerId": "delete_account", + "enabled": false, + "defaultAction": false, + "priority": 60, + "config": {} + }, + { + "alias": "webauthn-register", + "name": "Webauthn Register", + "providerId": "webauthn-register", + "enabled": true, + "defaultAction": false, + "priority": 70, + "config": {} + }, + { + "alias": "webauthn-register-passwordless", + "name": "Webauthn Register Passwordless", + "providerId": "webauthn-register-passwordless", + "enabled": true, + "defaultAction": false, + "priority": 80, + "config": {} + }, + { + "alias": "VERIFY_PROFILE", + "name": "Verify Profile", + "providerId": "VERIFY_PROFILE", + "enabled": true, + "defaultAction": false, + "priority": 90, + "config": {} + }, + { + "alias": "delete_credential", + "name": "Delete Credential", + "providerId": "delete_credential", + "enabled": true, + "defaultAction": false, + "priority": 100, + "config": {} + }, + { + "alias": "update_user_locale", + "name": "Update User Locale", + "providerId": "update_user_locale", + "enabled": true, + "defaultAction": false, + "priority": 1000, + "config": {} + } + ], + "browserFlow": "browser", + "registrationFlow": "registration", + "directGrantFlow": "direct grant", + "resetCredentialsFlow": "reset credentials", + "clientAuthenticationFlow": "clients", + "dockerAuthenticationFlow": "docker auth", + "firstBrokerLoginFlow": "first broker login", + "attributes": { + "cibaBackchannelTokenDeliveryMode": "poll", + "cibaAuthRequestedUserHint": "login_hint", + "clientOfflineSessionMaxLifespan": "0", + "oauth2DevicePollingInterval": "5", + "clientSessionIdleTimeout": "0", + "clientOfflineSessionIdleTimeout": "0", + "cibaInterval": "5", + "realmReusableOtpCode": "false", + "cibaExpiresIn": "120", + "oauth2DeviceCodeLifespan": "600", + "parRequestUriLifespan": "60", + "clientSessionMaxLifespan": "0", + "frontendUrl": "", + "organizationsEnabled": "false", + "acr.loa.map": "{}", + "adminEventsExpiration": "360" + }, + "keycloakVersion": "26.0.2", + "userManagedAccessAllowed": false, + "organizationsEnabled": false, + "clientProfiles": { + "profiles": [] + }, + "clientPolicies": { + "policies": [] + } +} \ No newline at end of file diff --git a/doc/tools/ext_oauth2_server/gen_keycloak.sh b/doc/tools/ext_oauth2_server/gen_keycloak.sh new file mode 100644 index 000000000..0b84eb301 --- /dev/null +++ b/doc/tools/ext_oauth2_server/gen_keycloak.sh @@ -0,0 +1,595 @@ +#!/bin/bash + +# Define various file and directory paths +local_cert_dir="${PWD}/etc/ssl/localcerts" +ca_key_file="ca.key" +ca_cert_file="ca.pem" +keycloak_key_file="keycloak.key" +keycloak_cert_file="keycloak.pem" +keycloak_csr_file="keycloak.csr" +keycloak_conf_dir="${PWD}/etc/keycloak/conf" +keycloak_conf_file="keycloak.conf" +keycloak_admin_user="admin" +keycloak_admin_pass="admin" +keycloak_version="26.0.2" +keycloak_http_port="8080" +keycloak_https_port="8443" +keycloak_host="127.0.0.1" +keycloak_realm_file="base_realm.json" +keycloak_realm_default_dir="/opt/keycloak/data/import/example-realm.json" +client_key_file="client.key" +client_cert_file="client.pem" +client_csr_file="client.csr" +tacker_host="127.0.0.1" +tacker_key_file="tacker.key" +tacker_cert_file="tacker.pem" +tacker_csr_file="tacker.csr" +TIME_OUT=600 # approximately 10min +CLIENT_ID='tacker_service' +KEY_PATH="${PWD}/private_key.pem" +CLIENT_SECRET=iIK6lARLzJgoQQyMyoymNYrGTDuR0733S +ISSUER='tacker_service' +SUBJECT='tacker_service' +SCOPE='tacker_scope' +OID_URL=http://${keycloak_host}:${keycloak_http_port}/realms/testrealm/.well-known/openid-configuration +HTTP_ENDPOINT=http://${keycloak_host}:${keycloak_http_port}/realms/testrealm/protocol/openid-connect/token +HTTPS_ENDPOINT=https://${keycloak_host}:${keycloak_https_port}/realms/testrealm/protocol/openid-connect/token + +declare -a ENUM_VALUES=(\ +"client_secret_post" \ +"client_secret_basic" \ +"private_key_jwt" \ +"client_secret_jwt" \ +"tls_client_auth") + +# Function to display help +function display_help { + cat << EOS +Usage: $0 [options] + +Description: +This script will allow you to build and start Keycloak Docker with predefined +config pattern. + +Available Options: +-h, --help Show this help message and exit +-n, --no-server Generate keycloak configuration file and realm.json only + without actually starting server + +Available Authentication Types: +1. client_secret_post +2. client_secret_basic +3. private_key_jwt +4. client_secret_jwt +5. tls_client_auth + +Steps to Run the Script: +1. Run the script with the -h option to display this help message. +2. Select the authentication type from the available options. +3. Enter the required information for the selected authentication type. +4. The script will generate the certificates and Keycloak configuration file. +5. The script will start the Keycloak Docker container. + +Note: +Make sure to have Docker installed and running on your system. +Make sure to have the required dependencies installed on your system. +EOS +} + +# Function to check if a command exists and handle errors +function check_command { + local command_to_check="$1" + local error_message="$2" + + if ! ${command_to_check} > /dev/null 2>&1; then + echo "${error_message}" >&2 + exit 1 + fi +} + + +# Function to create certificates +function create_certificates { + echo "Generating Certificate" + if check_file "${local_cert_dir}/${keycloak_key_file}"; then + echo "Certificate will generate" + else + return 0 + fi + + + openssl genrsa -out "${local_cert_dir}/${ca_key_file}" 4096 + openssl req -new -x509 -key "${local_cert_dir}/${ca_key_file}" \ + -out "${local_cert_dir}/${ca_cert_file}" -days 365 -subj \ + "/C=JP/ST=Tokyo/L=Chiyoda-ku/O=OpenstackORG/CN=root_a.openstack.host" + + cat << EOF > ./extfile +subjectAltName=IP.1:${keycloak_host} +EOF + + openssl genrsa -out "${local_cert_dir}/${keycloak_key_file}" 4096 + openssl req -new -key "${local_cert_dir}/${keycloak_key_file}" \ + -out "${local_cert_dir}/${keycloak_csr_file}" \ + -subj "/C=JP/ST=Tokyo/L=Chiyoda-ku/O=OpenstackORG/CN=${keycloak_host}" + openssl x509 -req -days 365 -sha384 -CA "${local_cert_dir}/${ca_cert_file}" \ + -CAkey "${local_cert_dir}/${ca_key_file}" \ + -CAcreateserial -extfile ./extfile \ + -in "${local_cert_dir}/${keycloak_csr_file}" \ + -out "${local_cert_dir}/${keycloak_cert_file}" + + rm -f ./extfile + + cat << EOF > ./extfile +subjectAltName=IP.1:${tacker_host} +EOF + + openssl genrsa -out "${local_cert_dir}/${tacker_key_file}" 4096 + openssl req -new -key "${local_cert_dir}/${tacker_key_file}" \ + -out "${local_cert_dir}/${tacker_csr_file}" \ + -subj "/C=JP/ST=Tokyo/L=Chiyoda-ku/O=OpenstackORG/CN=${tacker_host}" + openssl x509 -req -days 365 -sha384 \ + -CA "${local_cert_dir}/${ca_cert_file}" \ + -CAkey "${local_cert_dir}/${ca_key_file}" \ + -CAcreateserial -extfile ./extfile \ + -in "${local_cert_dir}/${tacker_csr_file}" \ + -out "${local_cert_dir}/${tacker_cert_file}" + + rm -f ./extfile + + openssl genrsa -out "${local_cert_dir}/${client_key_file}" 4096 + openssl req -new -key "${local_cert_dir}/${client_key_file}" \ + -out "${local_cert_dir}/${client_csr_file}" \ + -subj "/C=JP/ST=Tokyo/L=Chiyoda-ku/O=OpenstackORG/CN=client" + openssl x509 -req -days 365 -sha384 \ + -CA "${local_cert_dir}/${ca_cert_file}" \ + -CAkey "${local_cert_dir}/${ca_key_file}" \ + -CAcreateserial \ + -in "${local_cert_dir}/${client_csr_file}" \ + -out "${local_cert_dir}/${client_cert_file}" + + chmod 644 "${local_cert_dir}/${keycloak_key_file}" + + echo "-------------------------" + echo "" + +} + +function base64url_encode { + echo -n "$1" | base64 -w 0 | tr '/+' '_-' | tr -d '=' +} + +function generate_uuid { + if command -v uuidgen > /dev/null; then + uuidgen + else + cat /proc/sys/kernel/random/uuid + fi +} + +# Function to generate client_assertion +function create_client_assertion { + KEY_TYPE=$1 + AUDIENCE=$2 + # Set create (iat) and expire (exp) times + CREATE_TIME=$(date +%s) + EXPIRE_TIME=$((CREATE_TIME + 300)) # Current time + 5 minutes (300 seconds) + + # Generate UUID for jti claim + JTI=$(generate_uuid) + # Create JWT header + if [ "${KEY_TYPE}" = "secret" ]; then + HEADER='{"alg":"HS256","typ":"JWT"}' + else + HEADER='{"alg":"RS256","typ":"JWT"}' + fi + HEADER_BASE64=$(base64url_encode "${HEADER}") + + # Create JWT payload + PAYLOAD='{ + "iss": "'${ISSUER}'", + "sub": "'${SUBJECT}'", + "aud": "'${AUDIENCE}'", + "iat": "'${CREATE_TIME}'", + "exp": "'${EXPIRE_TIME}'", + "jti": "'${JTI}'" + }' + + PAYLOAD_BASE64=$(base64url_encode "${PAYLOAD}") + + # Combine header and payload + UNSIGNED_TOKEN="${HEADER_BASE64}.${PAYLOAD_BASE64}" + # Sign the token + if [ "${KEY_TYPE}" = "secret" ]; then + # Sign with secret key (HS256) + hexsecret=$(echo -n "${CLIENT_SECRET}" \ + | xxd -p \ + | paste -sd "") + SIGNATURE=$(echo -n "${UNSIGNED_TOKEN}" \ + | openssl dgst -sha256 -mac HMAC -macopt hexkey:${hexsecret} -binary \ + | base64 \ + | tr '/+' '_-' \ + | tr -d '=') + else + # Sign with private key (RS256) + SIGNATURE=$(echo -n "${UNSIGNED_TOKEN}" \ + | openssl dgst -sha256 -sign "${KEY_PATH}" \ + | base64 \ + | tr '/+' '_-' \ + | tr -d '=') + fi + + # Create the complete JWT + JWT="${UNSIGNED_TOKEN}.${SIGNATURE}" + echo ${JWT} + +} + +# Function to generate Keycloak configuration file +function gen_keycloak_conf { + echo "Creating Keycloak config" + cat <<-EOF > ${keycloak_conf_file} +hostname=${keycloak_host} +https-certificate-file=\${kc.home.dir}/conf/${keycloak_cert_file} +https-certificate-key-file=\${kc.home.dir}/conf/${keycloak_key_file} +https-trust-store-file=\${kc.home.dir}/conf/${ca_cert_file} +https-client-auth=request +truststore-file-hostname-verification-policy=ANY +EOF + + mv ${keycloak_conf_file} ${keycloak_conf_dir}/${keycloak_conf_file} + echo "-------------------------" + echo "" +} + +# Function to start Keycloak Docker container +function start_docker { + echo "Starting Keycloak Server" + echo "" + docker stop keycloak && docker rm keycloak + docker run -d --name keycloak \ + -p ${keycloak_http_port}:8080 \ + -p ${keycloak_https_port}:8443 \ + -e KEYCLOAK_ADMIN=${keycloak_admin_user} \ + -e KEYCLOAK_ADMIN_PASSWORD=${keycloak_admin_pass} \ + -v ${local_cert_dir}/${keycloak_cert_file}:/opt/keycloak/conf/${keycloak_cert_file} \ + -v ${local_cert_dir}/${ca_cert_file}:/opt/keycloak/conf/${ca_cert_file} \ + -v ${local_cert_dir}/${keycloak_key_file}:/opt/keycloak/conf/${keycloak_key_file} \ + -v ${keycloak_conf_dir}/${keycloak_conf_file}:/opt/keycloak/conf/${keycloak_conf_file} \ + -v ${keycloak_conf_dir}/${keycloak_realm_file}:${keycloak_realm_default_dir} \ + quay.io/keycloak/keycloak:${keycloak_version} start-dev --import-realm +} + +# Function to print the menu and get user input +function get_auth_type { + echo "Select the client credential grant flow type for keycloak server :" + for i in "${!ENUM_VALUES[@]}"; do + echo "$((i+1)). ${ENUM_VALUES[$i]}" + done + + while true; do + read -p "Enter your choice (1-${#ENUM_VALUES[@]}): " choice + if [[ "$choice" =~ ^[1-${#ENUM_VALUES[@]}]$ ]]; then + return $((choice-1)) + else + echo "Invalid choice. Please try again." + fi + done +} + +# Function to check if a file exists and handle user input +function check_file { + local filename="$1" + + if [ -e "${filename}" ]; then + echo "Certificate files already exist." + read -p "Overwrite? (y/n) [default:n]: " choice + case "${choice}" in + y|Y ) + echo "${filename} will overwrite" + return 0 + ;; + * ) + echo "Existing file will be used" + echo "-------------------------" + echo "" + return 1 + ;; + esac + else + return 0 + fi +} + +# Function to replace a string in a file +function replace_string { + local replace_file="$1" + local search_string="$2" + local replace_string="$3" + local info_message="$4" + + if [ ! -f "${replace_file}" ]; then + echo "Error: File '${replace_file}' not found." >&2 + return 1 + fi + + sed -i "s|${search_string}|${replace_string}|g" "${replace_file}" + + if [ $? -eq 0 ]; then + echo "${info_message}" + echo "-------------------------" + echo "" + else + echo "Error: Failed to replace string in file." >&2 + return 1 + fi +} + + +# Function to set OpenStack parameters in the Keycloak realm file +function set_os_param { + local realm_file="${keycloak_conf_dir}/${keycloak_realm_file}" + + read -p "Enter OS username[default:nfv_user]: " os_username + replace_string ${realm_file} "os_tacker_username" ${os_username:-nfv_user} \ + "Successfully set OS username with ${os_username:-nfv_user}"; + + while true; do + read -p "Enter OS user id: " os_user_id + if [ -n "${os_user_id}" ]; then + replace_string ${realm_file} "os_tacker_user_id" ${os_user_id} \ + "Successfully set OS user id with ${os_user_id}" + break + else + echo "You have to set OS user id" + fi + done + + read -p "Enter OS user domain id[default:default]: " os_user_domain_id + replace_string ${realm_file} "os_tacker_user_domain_id" \ + ${os_user_domain_id:-default} \ + "Successfully set OS user domain id with ${os_user_domain_id:-default}"; + + read -p "Enter OS user domain name[default:Default]: " os_user_domain_name + replace_string ${realm_file} "os_tacker_user_domain_name" \ + ${os_user_domain_name:-default} \ + "Successfully set OS user domain name with ${os_user_domain_name:-default}"; + + read -p "Enter OS project name[default:nfv]: " os_project_name + replace_string ${realm_file} "os_tacker_project_name" ${os_project_name:-nfv} \ + "Successfully set OS project name with ${os_project_name:-nfv}"; + + while true; do + read -p "Enter OS project id: " os_project_id + if [ -n "${os_project_id}" ]; then + replace_string ${realm_file} "os_tacker_project_id" ${os_project_id} \ + "Successfully set OS Project id with ${os_project_id}"; break + else + echo "You have to set OS user id" + fi + done + + read -p "Enter OS project domain id[default:default]: " os_project_domain_id + replace_string ${realm_file} "os_tacker_project_domain_id" \ + ${os_project_domain_id:-default} \ + "Successfully set OS project domain id with ${os_project_domain_id:-default}"; + + read -p "Enter OS project domain name[default:Default]: " os_project_domain_name + replace_string ${realm_file} "os_tacker_project_domain_name" \ + ${os_project_domain_id:-Default} \ + "Successfully set OS project domain name with ${os_project_domain_id:-default}"; + + read -p "Enter OS user roles[default:admin,member,reader]: " os_user_roles + replace_string ${realm_file} "os_tacker_roles" \ + ${os_user_roles:-'admin,member,reader'} \ + "Successfully set OS user roles with ${os_user_roles:-'admin,member,reader'}"; + +} + +function wait_server { + # Main loop to check API + echo -en Waiting Keycloak Server to start...... + while [ ${TIME_OUT} -ge 0 ]; do + + # Get HTTP response code + RESPONSE=$(echo -en $(curl -I ${OID_URL} 2>/dev/null \ + | head -n 1 \ + | awk -F" " '{print $2}')OK) + + if [ "${RESPONSE}" = "200OK" ]; then + echo "" + echo -e "Keycloak server is started successfully." + break + else + for X in '-' '/' '|' '\'; do echo -en "\b\b\b[$X]" + TIME_OUT=$((TIME_OUT - 1)) + sleep 1 + done + fi + done + + if [ ${TIME_OUT} -le 0 ]; then + echo "" + echo "Time out for waiting the server to get started." + echo "Use \"docker logs\" or \"docker ps\" command to check server status." + exit 1 + fi +} + +# Function to generate private key and set public cert to realm.json +function set_private_key { + echo "Generating private key ${KEY_PATH}" + openssl req -x509 -newkey rsa:2048 -keyout ${KEY_PATH} \ + -out ./cert.pem -days 365 -nodes -subj "/CN=YourCommonName" \ + -config <(echo "[req]"; echo "distinguished_name=req_distinguished_name"; \ + echo "[req_distinguished_name]") + + echo "-------------------------" + echo "" + + pub_cert=$(awk 'NR>2 { sub(/\r/, ""); printf "%s",last} { last=$0 }' \ + ./cert.pem) + + sed -i "s|os_public_cert_string|${pub_cert}|g" ${realm_file}; +} + + +# Main function +function main { + AUDIENCE=${HTTP_ENDPOINT} + base_command="curl -s -X POST ${HTTP_ENDPOINT} \ + -d 'scope=${SCOPE}' -d 'client_id=${SUBJECT}' \ + -d 'grant_type=client_credentials'" + no_server=false + # Create necessary directories and set permissions + while getopts ":hn-:" opt; do + case ${opt} in + h) + display_help + exit 0 + ;; + n) + no_server=true + ;; + -) + case "${OPTARG}" in + help) + display_help + exit 0 + ;; + no-server) + no_server=true + ;; + *) + echo "Unknown option --${OPTARG}" + exit 1 + ;; + esac + ;; + ?) + echo "Unknown option: -${OPTARG}" + exit 1 + ;; + esac + done + + if ${no_server}; then + echo "" + else + check_command "docker ps" \ + "Docker not found or permission denied. Check docker again." + fi + mkdir -p ${local_cert_dir} + mkdir -p ${keycloak_conf_dir} + chmod 755 ${keycloak_conf_dir} + + # Main script + set +e + get_auth_type + selected_index=$? + auth=${ENUM_VALUES[${selected_index}]} + echo "You selected: ${auth}" + echo "-------------------------" + echo "" + cp -f "${PWD}/${keycloak_realm_file}" "${keycloak_conf_dir}/${keycloak_realm_file}" + local realm_file="${keycloak_conf_dir}/${keycloak_realm_file}" + read -p "Enable Oauth2 certificate-bounded token? (y/n) [default:n] :" thumb + origin_string='"tls.client.certificate.bound.access.tokens": "false"' + replace_string='"tls.client.certificate.bound.access.tokens": "true"' + case ${thumb} in + y|Y ) + AUDIENCE=${HTTPS_ENDPOINT} + replace_string ${realm_file} "${origin_string}" "${replace_string}" \ + "Oauth2 certificate-bounded token is enabled." + base_command="curl -s -X POST ${HTTPS_ENDPOINT} \ + -d 'scope=${SCOPE}' -d 'client_id=${SUBJECT}' \ + -d 'grant_type=client_credentials' \ + --cacert ${local_cert_dir}/${ca_cert_file} \ + --cert ${local_cert_dir}/${client_cert_file} \ + --key ${local_cert_dir}/${client_key_file}" + ;; + * ) + echo "Oauth2 certificate-bounded token is disabled"; + echo "-------------------------" + echo "" + ;; + esac + + # Copy the appropriate realm file based on the selected auth type + case "${auth}" in + "client_secret_post" ) + replace_string "${realm_file}" "client_credential_grant_flow_type" \ + "client-secret" "Set auth type to client secret post." + LAST_MSG="client_secret\t\t: ${CLIENT_SECRET}" + base_command="${base_command} \ + -d 'client_secret=${CLIENT_SECRET}'" + ;; + "client_secret_basic" ) + replace_string "${realm_file}" "client_credential_grant_flow_type" \ + "client-secret" "Set auth type to client secret basic." + LAST_MSG="client_secret\t\t: ${CLIENT_SECRET}" + base_command="${base_command} \ + -u '${SUBJECT}:${CLIENT_SECRET}'" + ;; + "private_key_jwt" ) + sed -i 's|"use.jwks.url": "true"|"use.jwks.url": "false"|g' ${realm_file} + replace_string "${keycloak_conf_dir}/${keycloak_realm_file}" \ + "client_credential_grant_flow_type" \ + "client-jwt" "Set auth type to private key signed JWT." + LAST_MSG="private_key\t\t: ${KEY_PATH}" + set_private_key + CLIENT_ASSERTION=$(create_client_assertion privatekey ${AUDIENCE}) + base_command="${base_command} \ + -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ + -d 'client_assertion=${CLIENT_ASSERTION}'" + ;; + "client_secret_jwt" ) + replace_string "${keycloak_conf_dir}/${keycloak_realm_file}" \ + "client_credential_grant_flow_type" "client-secret-jwt" \ + "Set auth type to client secret signed JWT." + LAST_MSG="client_secret\t\t: ${CLIENT_SECRET}" + CLIENT_ASSERTION=$(create_client_assertion secret ${AUDIENCE}) + base_command="${base_command} \ + -d 'client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer' \ + -d 'client_assertion=${CLIENT_ASSERTION}'" + ;; + "tls_client_auth" ) + replace_string "${keycloak_conf_dir}/${keycloak_realm_file}" \ + "client_credential_grant_flow_type" "client-x509" \ + "Set auth type to tls client authentication." + ;; + esac + set_os_param + create_certificates + gen_keycloak_conf + if ${no_server}; then + echo "***********************************" + echo "A realm configuration file has been generated without starting the Keycloak server." + else + start_docker + wait_server + fi + + echo "###################################" + echo -e "HTTP endpoint\t\t: "${HTTP_ENDPOINT} + echo -e "HTTPS endpoint\t\t: ${HTTPS_ENDPOINT}" + echo -e "client_id\t\t: tacker_service, tacker_api_proj, tacker_api_domain" + echo -e ${LAST_MSG} + echo -e "scope\t\t\t: project_scope, domain_scope" + echo "* If you want to use other Keycloak server, import this realm.json" + echo -e "realm JSON file\t\t: "${keycloak_conf_dir}/${keycloak_realm_file} + echo "* Use the following keys and certificates for Tacker and client" + echo -e "RootCA certificate\t: "${local_cert_dir}/${ca_cert_file} + echo -e "Tacker certificate\t: "${local_cert_dir}/${tacker_cert_file} + echo -e "Tacker key\t\t: "${local_cert_dir}/${tacker_key_file} + echo -e "client certificate\t: "${local_cert_dir}/${client_cert_file} + echo -e "client key\t\t: "${local_cert_dir}/${client_cert_file} + echo "" + echo "------------------------------------" + echo "You can try getting a token using following command" + echo "" + echo ${base_command} + echo "###################################" +} + +# Run the main function +main "$@" \ No newline at end of file