AWX modernization: Moving forward

Thanks for your input, Eddie.

So if I understand correctly, it would still be possible to use a custom authentication layer through backend configuration, but no longer through the UI as it exists today.

That would be quite a significant change, especially for something like onboarding a new team: it would no longer be possible to add the LDAP mapping on the fly as with the legacy version. Instead, it would require updating the configuration and rolling out the AWX web and task pods again.

Please correct me if I am misunderstanding your point.

2 Likes

Could you go into some detail how you built it? Did you follow some of the steps described here: Documentation for running AWX from the devel branch · Issue #16117 · ansible/awx · GitHub or did you follow another path? :slight_smile:

1 Like

Hello,

I’ve been able to make it working with ldap and keycloak auth.

If i’ve forgot nothing, here was all i’ve done :

in the awx repo folder :

from django-ansible-base/docs/Installation.md at devel · ansible/django-ansible-base · GitHub

curl -s https://raw.githubusercontent.com/ansible/django-ansible-base/refs/heads/devel/requirements/requirements_authentication.in >> requirements/requirements_dev.txt

upgrade social-auth-core to avoid issue with IAT by having JWT_LEEWAY option

sed -i 's/^social-auth-core.*/social-auth-core>=4.7/' requirements/requirements_dev.txt
cat >> awx/settings/settings.py << 'EOF'
OIDC_LEEWAY = 60
JWT_LEEWAY = 60
EOF

From django-ansible-base/docs/Installation.md at devel · ansible/django-ansible-base · GitHub

sed -i "/INSTALLED_APPS = \[/a\\    'ansible_base.authentication'," awx/settings/defaults.py

some things are going to failed if still none

sed -i "s/SYSTEM_USERNAME = None/SYSTEM_USERNAME = 'awx'/" awx/settings/defaults.py

Add the possibility to have keycloak button in homepage

sed -i "/^from awx.main.views import handle_400/a\\
\\
from django.http import JsonResponse\\
from django.views import View\\
from ansible_base.authentication.views import UIAuth\\
\\
class AwxAuthView(View):\\
    def get(self, request):\\
        response = UIAuth.as_view()(request)\\
        data = response.data\\
        result = {}\\
        for sso in data.get('ssos', []):\\
            result[sso['type']] = {\\
                'login_url': sso['login_url']\\
            }\\
        return JsonResponse(result)" awx/urls.py

add openldap-devel in dnf in tools/ansible/roles/dockerfile/templates/Dockerfile.j2 to be able to build library for django-ansible-base auth.

sed -i 's/    xmlsec1-openssl-devel/    xmlsec1-openssl-devel \\\n    openldap-devel/' tools/ansible/roles/dockerfile/templates/Dockerfile.j2

Start building

eval "$(ssh-agent -s)"
git pull && nvm use 18 && make clean/ui ui && make ui/src/build && make docker-compose-build && make docker-compose

Once build and started, do some configuration from inside awx-manage shell_plus within docker :

from ansible_base.authentication.models import Authenticator
Authenticator.objects.filter(name="LDAP").delete()
Authenticator.objects.create(
    name="LDAP",
    enabled=True,
    type="ansible_base.authentication.authenticator_plugins.ldap",
    configuration={
        "SERVER_URI": ["ldaps://ldap_server"],
        "BIND_DN": "CN=account,OU=xxx,DC=xxx,DC=xxx,DC=xxx",
        "BIND_PASSWORD": "account_password",
    "START_TLS": False,
    "CONNECTION_OPTIONS": {
        "OPT_REFERRALS": 0,
        "OPT_NETWORK_TIMEOUT": 30,
        "OPT_X_TLS_REQUIRE_CERT": 0,
		"OPT_X_TLS_NEWCTX": 0
    },
    "USER_SEARCH": [
        "DC=xxx,DC=xxx,DC=xxx",
        "SCOPE_SUBTREE",
        "(cn=%(user)s)"
    ],
    "USER_DN_TEMPLATE": "",
    "USER_ATTR_MAP": {
        "email": "mail",
        "last_name": "sn",
        "first_name": "givenName"
    },
    "GROUP_SEARCH": [
        "DC=xxx,DC=xxx,DC=xxx",
        "SCOPE_SUBTREE",
        "(objectClass=group)"
    ],
    "GROUP_TYPE": "PosixGroupType",
    "GROUP_TYPE_PARAMS": {},
    "USER_FLAGS_BY_GROUP": {},
    "ORGANIZATION_MAP": {},
    "TEAM_MAP": {},
    }
)

Authenticator.objects.filter(name="Keycloak").delete()
Authenticator.objects.create(
    name="Keycloak",
    enabled=True,
    type="ansible_base.authentication.authenticator_plugins.keycloak",
    configuration={
		"AUDIENCE": "name_of_your_client",
        "ACCESS_TOKEN_URL": "https://keycloak/realms/my_realm/protocol/openid-connect/token",
        "AUTHORIZATION_URL": "https://keycloak/realms/my_realm/protocol/openid-connect/auth",
        "REVOKE_TOKEN_URL": "https://keycloak/realms/my_realm/protocol/openid-connect/revoke",
        "USERINFO_URL": "https://keycloak/realms/my_realm/protocol/openid-connect/userinfo",
		"PUBLIC_KEY": "public_key_of_your_realm",
        "KEY": "name_of_your_client",
        "SECRET": "secret_of_your_realm_or_client_i_forgot",

        # Mapping des attributs utilisateur
        "USERNAME_KEY": "preferred_username",  # must match username in LDAP
        "USER_ATTR_MAP": {
            "first_name": "given_name",
            "last_name": "family_name",
            "email": "email"
        },
    }
)

if you want to sync user between ldap and keycloak, launch this in awx-manage shell_plus :

ldap_auth = Authenticator.objects.get(name="LDAP")
keycloak_auth = Authenticator.objects.get(name="Keycloak")

keycloak_auth.auto_migrate_users_from.add(ldap_auth)
keycloak_auth.save()  
ldap_auth.auto_migrate_users_from.add(keycloak_auth)
ldap_auth.save()  

feel free to change a param inside the file awx/settings/defaults.py to force a reload of the AWX. check the log for error and try the logins !

NB : i haven’t tested anything after that.

4 Likes

How about refactoring AWX so that you don’t have to have a PhD in managing Kubernetes? I have a hundred other things to support without having to know Kubernetes to install and managed this thing. It’s way over complicated. How about a package that installs the whole thing without taking two days to get it all configured and running. And the idea that you need a Kubernetes cluster is nuts.

2 Likes

Hello,

There was no K8s implication in what was done :
It require linux and docker knowledge to understand how to build the docker image to make it run in local ( and play within it ).
It also require dev knowledge to :

  • Dig into the django-ansible-base code to understand how to configure the authenticator backend.
  • Change the ui code to get possibility to have the SSO button.

But i agree that this refactoring is not going well by seeing the lack of documentation and the absence of UI update since almost two year and is clearly outdated.

I also don’t understand how that non monolitic thing is going to be provided to users ( for exemple : knowing that SSO is actually almost mandatory in enterprise and is not included in the awx:devel image by default and thus require to build the image with it seems clearly strange to me. )

I also hope that they’ll provide another way to deploy it on K8S than the operator that require special access to the cluster…

Good luck with it !

It’s been almost 30 days now, again. Can you clarify as to how ‘soon’ soon will be?

‘soon’ is subjective, for a user it means in 5mins, for a dev in a few days, for a corporation … they measure in quarters

1 Like