summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelogs/fragments/75593-ansible-galaxy-keycloak-clientid.yml2
-rw-r--r--docs/docsite/rst/shared_snippets/galaxy_server_list.txt9
-rw-r--r--lib/ansible/cli/galaxy.py7
-rw-r--r--lib/ansible/galaxy/token.py8
-rw-r--r--test/units/galaxy/test_token.py43
5 files changed, 64 insertions, 5 deletions
diff --git a/changelogs/fragments/75593-ansible-galaxy-keycloak-clientid.yml b/changelogs/fragments/75593-ansible-galaxy-keycloak-clientid.yml
new file mode 100644
index 0000000000..bf8ae15728
--- /dev/null
+++ b/changelogs/fragments/75593-ansible-galaxy-keycloak-clientid.yml
@@ -0,0 +1,2 @@
+minor_changes:
+ - ansible-galaxy - Allow specification of client_id override value for Keycloak Token (https://github.com/ansible/ansible/issues/75593).
diff --git a/docs/docsite/rst/shared_snippets/galaxy_server_list.txt b/docs/docsite/rst/shared_snippets/galaxy_server_list.txt
index 47151079e6..abc624514b 100644
--- a/docs/docsite/rst/shared_snippets/galaxy_server_list.txt
+++ b/docs/docsite/rst/shared_snippets/galaxy_server_list.txt
@@ -28,7 +28,7 @@ The following example shows how to configure multiple servers:
.. code-block:: ini
[galaxy]
- server_list = automation_hub, my_org_hub, release_galaxy, test_galaxy
+ server_list = automation_hub, my_org_hub, release_galaxy, test_galaxy, my_galaxy_ng
[galaxy_server.automation_hub]
url=https://cloud.redhat.com/api/automation-hub/
@@ -48,6 +48,12 @@ The following example shows how to configure multiple servers:
url=https://galaxy-dev.ansible.com/
token=my_test_token
+ [galaxy_server.my_galaxy_ng]
+ url=http://my_galaxy_ng:8000/api/automation-hub/
+ auth_url=http://my_keycloak:8080/auth/realms/myco/protocol/openid-connect/token
+ client_id=galaxy-ng
+ token=my_keycloak_access_token
+
.. note::
You can use the ``--server`` command line argument to select an explicit Galaxy server in the ``server_list`` and
the value of this argument should match the name of the server. To use a server not in the server list, set the value to the URL to access that server (all servers in the server list will be ignored). Also you cannot use the ``--api-key`` argument for any of the predefined servers. You can only use the ``api_key`` argument if you did not define a server list or if you specify a URL in the
@@ -67,6 +73,7 @@ define the following keys:
* ``password``: The password to use, in conjunction with ``username``, for basic authentication.
* ``auth_url``: The URL of a Keycloak server 'token_endpoint' if using SSO authentication (for example, Automation Hub). Mutually exclusive with ``username``. Requires ``token``.
* ``validate_certs``: Whether or not to verify TLS certificates for the Galaxy server. This defaults to True unless the ``--ignore-certs`` option is provided or ``GALAXY_IGNORE_CERTS`` is configured to True.
+* ``client_id``: The Keycloak token's client_id to use for authentication. Requires ``auth_url`` and ``token``. The default ``client_id`` is cloud-services to work with Red Hat SSO.
As well as defining these server options in the ``ansible.cfg`` file, you can also define them as environment variables.
The environment variable is in the form ``ANSIBLE_GALAXY_SERVER_{{ id }}_{{ key }}`` where ``{{ id }}`` is the upper
diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py
index e57db6e796..cc9a813ef2 100644
--- a/lib/ansible/cli/galaxy.py
+++ b/lib/ansible/cli/galaxy.py
@@ -62,7 +62,8 @@ SERVER_DEF = [
('token', False),
('auth_url', False),
('v3', False),
- ('validate_certs', False)
+ ('validate_certs', False),
+ ('client_id', False),
]
@@ -498,6 +499,7 @@ class GalaxyCLI(CLI):
# auth_url is used to create the token, but not directly by GalaxyAPI, so
# it doesn't need to be passed as kwarg to GalaxyApi
auth_url = server_options.pop('auth_url', None)
+ client_id = server_options.pop('client_id', None)
token_val = server_options['token'] or NoTokenSentinel
username = server_options['username']
available_api_versions = None
@@ -524,7 +526,8 @@ class GalaxyCLI(CLI):
if auth_url:
server_options['token'] = KeycloakToken(access_token=token_val,
auth_url=auth_url,
- validate_certs=validate_certs)
+ validate_certs=validate_certs,
+ client_id=client_id)
else:
# The galaxy v1 / github / django / 'Token'
server_options['token'] = GalaxyToken(token=token_val)
diff --git a/lib/ansible/galaxy/token.py b/lib/ansible/galaxy/token.py
index 11a12ce45a..4455fd01c1 100644
--- a/lib/ansible/galaxy/token.py
+++ b/lib/ansible/galaxy/token.py
@@ -50,14 +50,18 @@ class KeycloakToken(object):
token_type = 'Bearer'
- def __init__(self, access_token=None, auth_url=None, validate_certs=True):
+ def __init__(self, access_token=None, auth_url=None, validate_certs=True, client_id=None):
self.access_token = access_token
self.auth_url = auth_url
self._token = None
self.validate_certs = validate_certs
+ self.client_id = client_id
+ if self.client_id is None:
+ self.client_id = 'cloud-services'
def _form_payload(self):
- return 'grant_type=refresh_token&client_id=cloud-services&refresh_token=%s' % self.access_token
+ return 'grant_type=refresh_token&client_id=%s&refresh_token=%s' % (self.client_id,
+ self.access_token)
def get(self):
if self._token:
diff --git a/test/units/galaxy/test_token.py b/test/units/galaxy/test_token.py
index 94449e28e9..13426688e3 100644
--- a/test/units/galaxy/test_token.py
+++ b/test/units/galaxy/test_token.py
@@ -8,8 +8,10 @@ __metaclass__ = type
import os
import pytest
+from units.compat.mock import MagicMock
import ansible.constants as C
+from ansible.cli.galaxy import GalaxyCLI, SERVER_DEF
from ansible.galaxy.token import GalaxyToken, NoTokenSentinel
from ansible.module_utils._text import to_bytes, to_text
@@ -32,6 +34,47 @@ def b_token_file(request, tmp_path_factory):
C.GALAXY_TOKEN_PATH = orig_token_path
+def test_client_id(monkeypatch):
+ monkeypatch.setattr(C, 'GALAXY_SERVER_LIST', ['server1', 'server2'])
+
+ test_server_config = {option[0]: None for option in SERVER_DEF}
+ test_server_config.update(
+ {
+ 'url': 'http://my_galaxy_ng:8000/api/automation-hub/',
+ 'auth_url': 'http://my_keycloak:8080/auth/realms/myco/protocol/openid-connect/token',
+ 'client_id': 'galaxy-ng',
+ 'token': 'access_token',
+ }
+ )
+
+ test_server_default = {option[0]: None for option in SERVER_DEF}
+ test_server_default.update(
+ {
+ 'url': 'https://cloud.redhat.com/api/automation-hub/',
+ 'auth_url': 'https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token',
+ 'token': 'access_token',
+ }
+ )
+
+ get_plugin_options = MagicMock(side_effect=[test_server_config, test_server_default])
+ monkeypatch.setattr(C.config, 'get_plugin_options', get_plugin_options)
+
+ cli_args = [
+ 'ansible-galaxy',
+ 'collection',
+ 'install',
+ 'namespace.collection:1.0.0',
+ ]
+
+ galaxy_cli = GalaxyCLI(args=cli_args)
+ mock_execute_install = MagicMock()
+ monkeypatch.setattr(galaxy_cli, '_execute_install_collection', mock_execute_install)
+ galaxy_cli.run()
+
+ assert galaxy_cli.api_servers[0].token.client_id == 'galaxy-ng'
+ assert galaxy_cli.api_servers[1].token.client_id == 'cloud-services'
+
+
def test_token_explicit(b_token_file):
assert GalaxyToken(token="explicit").get() == "explicit"