mirror of
https://github.com/ansible/awx.git
synced 2026-02-26 15:36:04 -03:30
Add dump_auth_config management cmd (for SAML and LDAP) (#14947)
* Add dump_auth_config management cmd - Dump SAML config from AWX to DAB authenticator config in json format * Add dumping of LDAP settings * add test for command * Fix is_enabled * fix command name typo Co-authored-by: Hao Liu <44379968+TheRealHaoLiu@users.noreply.github.com> * add fields to config, add name to data * break out IDP values * change test fields and value comparison * edit help text, reformat settings --------- Co-authored-by: jessicamack <jmack@redhat.com>
This commit is contained in:
179
awx/main/management/commands/dump_auth_config.py
Normal file
179
awx/main/management/commands/dump_auth_config.py
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.conf import settings
|
||||||
|
from awx.conf import settings_registry
|
||||||
|
|
||||||
|
|
||||||
|
class Command(BaseCommand):
|
||||||
|
help = 'Dump the current auth configuration in django_ansible_base.authenticator format, currently supports LDAP and SAML'
|
||||||
|
|
||||||
|
DAB_SAML_AUTHENTICATOR_KEYS = {
|
||||||
|
"SP_ENTITY_ID": True,
|
||||||
|
"SP_PUBLIC_CERT": True,
|
||||||
|
"SP_PRIVATE_KEY": True,
|
||||||
|
"ORG_INFO": True,
|
||||||
|
"TECHNICAL_CONTACT": True,
|
||||||
|
"SUPPORT_CONTACT": True,
|
||||||
|
"SP_EXTRA": False,
|
||||||
|
"SECURITY_CONFIG": False,
|
||||||
|
"EXTRA_DATA": False,
|
||||||
|
"ENABLED_IDPS": True,
|
||||||
|
"CALLBACK_URL": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
DAB_LDAP_AUTHENTICATOR_KEYS = {
|
||||||
|
"SERVER_URI": True,
|
||||||
|
"BIND_DN": False,
|
||||||
|
"BIND_PASSWORD": False,
|
||||||
|
"CONNECTION_OPTIONS": False,
|
||||||
|
"GROUP_TYPE": True,
|
||||||
|
"GROUP_TYPE_PARAMS": True,
|
||||||
|
"GROUP_SEARCH": False,
|
||||||
|
"START_TLS": False,
|
||||||
|
"USER_DN_TEMPLATE": True,
|
||||||
|
"USER_ATTR_MAP": True,
|
||||||
|
"USER_SEARCH": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_awx_ldap_settings(self) -> dict[str, dict[str, Any]]:
|
||||||
|
awx_ldap_settings = {}
|
||||||
|
|
||||||
|
for awx_ldap_setting in settings_registry.get_registered_settings(category_slug='ldap'):
|
||||||
|
key = awx_ldap_setting.removeprefix("AUTH_LDAP_")
|
||||||
|
value = getattr(settings, awx_ldap_setting, None)
|
||||||
|
awx_ldap_settings[key] = value
|
||||||
|
|
||||||
|
grouped_settings = {}
|
||||||
|
|
||||||
|
for key, value in awx_ldap_settings.items():
|
||||||
|
match = re.search(r'(\d+)', key)
|
||||||
|
index = int(match.group()) if match else 0
|
||||||
|
new_key = re.sub(r'\d+_', '', key)
|
||||||
|
|
||||||
|
if index not in grouped_settings:
|
||||||
|
grouped_settings[index] = {}
|
||||||
|
|
||||||
|
grouped_settings[index][new_key] = value
|
||||||
|
if new_key == "GROUP_TYPE" and value:
|
||||||
|
grouped_settings[index][new_key] = type(value).__name__
|
||||||
|
|
||||||
|
if new_key == "SERVER_URI" and value:
|
||||||
|
value = value.split(", ")
|
||||||
|
|
||||||
|
return grouped_settings
|
||||||
|
|
||||||
|
def is_enabled(self, settings, keys):
|
||||||
|
for key, required in keys.items():
|
||||||
|
if required and not settings.get(key):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_awx_saml_settings(self) -> dict[str, Any]:
|
||||||
|
awx_saml_settings = {}
|
||||||
|
for awx_saml_setting in settings_registry.get_registered_settings(category_slug='saml'):
|
||||||
|
awx_saml_settings[awx_saml_setting.removeprefix("SOCIAL_AUTH_SAML_")] = getattr(settings, awx_saml_setting, None)
|
||||||
|
|
||||||
|
return awx_saml_settings
|
||||||
|
|
||||||
|
def format_config_data(self, enabled, awx_settings, type, keys, name):
|
||||||
|
config = {
|
||||||
|
"type": f"awx.authentication.authenticator_plugins.{type}",
|
||||||
|
"name": name,
|
||||||
|
"enabled": enabled,
|
||||||
|
"create_objects": True,
|
||||||
|
"users_unique": False,
|
||||||
|
"remove_users": True,
|
||||||
|
"configuration": {},
|
||||||
|
}
|
||||||
|
for k in keys:
|
||||||
|
v = awx_settings.get(k)
|
||||||
|
config["configuration"].update({k: v})
|
||||||
|
|
||||||
|
if type == "saml":
|
||||||
|
idp_to_key_mapping = {
|
||||||
|
"url": "IDP_URL",
|
||||||
|
"x509cert": "IDP_X509_CERT",
|
||||||
|
"entity_id": "IDP_ENTITY_ID",
|
||||||
|
"attr_email": "IDP_ATTR_EMAIL",
|
||||||
|
"attr_groups": "IDP_GROUPS",
|
||||||
|
"attr_username": "IDP_ATTR_USERNAME",
|
||||||
|
"attr_last_name": "IDP_ATTR_LAST_NAME",
|
||||||
|
"attr_first_name": "IDP_ATTR_FIRST_NAME",
|
||||||
|
"attr_user_permanent_id": "IDP_ATTR_USER_PERMANENT_ID",
|
||||||
|
}
|
||||||
|
for idp_name in awx_settings.get("ENABLED_IDPS", {}):
|
||||||
|
for key in idp_to_key_mapping:
|
||||||
|
value = awx_settings["ENABLED_IDPS"][idp_name].get(key)
|
||||||
|
if value is not None:
|
||||||
|
config["name"] = idp_name
|
||||||
|
config["configuration"].update({idp_to_key_mapping[key]: value})
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
def add_arguments(self, parser):
|
||||||
|
parser.add_argument(
|
||||||
|
"output_file",
|
||||||
|
nargs="?",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="Output JSON file path",
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle(self, *args, **options):
|
||||||
|
try:
|
||||||
|
data = []
|
||||||
|
|
||||||
|
# dump SAML settings
|
||||||
|
awx_saml_settings = self.get_awx_saml_settings()
|
||||||
|
awx_saml_enabled = self.is_enabled(awx_saml_settings, self.DAB_SAML_AUTHENTICATOR_KEYS)
|
||||||
|
if awx_saml_enabled:
|
||||||
|
awx_saml_name = awx_saml_settings["ENABLED_IDPS"]
|
||||||
|
data.append(
|
||||||
|
self.format_config_data(
|
||||||
|
awx_saml_enabled,
|
||||||
|
awx_saml_settings,
|
||||||
|
"saml",
|
||||||
|
self.DAB_SAML_AUTHENTICATOR_KEYS,
|
||||||
|
awx_saml_name,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# dump LDAP settings
|
||||||
|
awx_ldap_group_settings = self.get_awx_ldap_settings()
|
||||||
|
for awx_ldap_name, awx_ldap_settings in enumerate(awx_ldap_group_settings.values()):
|
||||||
|
enabled = self.is_enabled(awx_ldap_settings, self.DAB_LDAP_AUTHENTICATOR_KEYS)
|
||||||
|
if enabled:
|
||||||
|
data.append(
|
||||||
|
self.format_config_data(
|
||||||
|
enabled,
|
||||||
|
awx_ldap_settings,
|
||||||
|
"ldap",
|
||||||
|
self.DAB_LDAP_AUTHENTICATOR_KEYS,
|
||||||
|
str(awx_ldap_name),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
# write to file if requested
|
||||||
|
if options["output_file"]:
|
||||||
|
# Define the path for the output JSON file
|
||||||
|
output_file = options["output_file"]
|
||||||
|
|
||||||
|
# Ensure the directory exists
|
||||||
|
os.makedirs(os.path.dirname(output_file), exist_ok=True)
|
||||||
|
|
||||||
|
# Write data to the JSON file
|
||||||
|
with open(output_file, "w") as f:
|
||||||
|
json.dump(data, f, indent=4)
|
||||||
|
|
||||||
|
self.stdout.write(self.style.SUCCESS(f"Auth config data dumped to {output_file}"))
|
||||||
|
else:
|
||||||
|
self.stdout.write(json.dumps(data, indent=4))
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.stdout.write(self.style.ERROR(f"An error occurred: {str(e)}"))
|
||||||
|
sys.exit(1)
|
||||||
122
awx/main/tests/unit/commands/test_dump_auth_config.py
Normal file
122
awx/main/tests/unit/commands/test_dump_auth_config.py
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
from io import StringIO
|
||||||
|
import json
|
||||||
|
from django.core.management import call_command
|
||||||
|
from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
|
||||||
|
settings_dict = {
|
||||||
|
"SOCIAL_AUTH_SAML_SP_ENTITY_ID": "SP_ENTITY_ID",
|
||||||
|
"SOCIAL_AUTH_SAML_SP_PUBLIC_CERT": "SP_PUBLIC_CERT",
|
||||||
|
"SOCIAL_AUTH_SAML_SP_PRIVATE_KEY": "SP_PRIVATE_KEY",
|
||||||
|
"SOCIAL_AUTH_SAML_ORG_INFO": "ORG_INFO",
|
||||||
|
"SOCIAL_AUTH_SAML_TECHNICAL_CONTACT": "TECHNICAL_CONTACT",
|
||||||
|
"SOCIAL_AUTH_SAML_SUPPORT_CONTACT": "SUPPORT_CONTACT",
|
||||||
|
"SOCIAL_AUTH_SAML_SP_EXTRA": "SP_EXTRA",
|
||||||
|
"SOCIAL_AUTH_SAML_SECURITY_CONFIG": "SECURITY_CONFIG",
|
||||||
|
"SOCIAL_AUTH_SAML_EXTRA_DATA": "EXTRA_DATA",
|
||||||
|
"SOCIAL_AUTH_SAML_ENABLED_IDPS": {
|
||||||
|
"Keycloak": {
|
||||||
|
"attr_last_name": "last_name",
|
||||||
|
"attr_groups": "groups",
|
||||||
|
"attr_email": "email",
|
||||||
|
"attr_user_permanent_id": "name_id",
|
||||||
|
"attr_username": "username",
|
||||||
|
"entity_id": "https://example.com/auth/realms/awx",
|
||||||
|
"url": "https://example.com/auth/realms/awx/protocol/saml",
|
||||||
|
"x509cert": "-----BEGIN CERTIFICATE-----\nMIIDDjCCAfYCCQCPBeVvpo8+VzANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCTkMxDzANBgNVBAcMBkR1cmhhbTEMMAoGA1UECgwDYXd4MQ4w\nDAYDVQQDDAVsb2NhbDAeFw0yNDAxMTgxNDA4MzFaFw0yNTAxMTcxNDA4MzFaMEkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOQzEPMA0GA1UEBwwGRHVyaGFtMQwwCgYD\nVQQKDANhd3gxDjAMBgNVBAMMBWxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAzouj93oyFXsHEABdPESh3CYpp5QJJBM4TLYIIolk6PFOFIVwBuFY\nfExi5w7Hh4A42lPM6RkrT+u3h7LV39H9MRUfqygOSmaxICTOI0sU9ROHc44fWWzN\n756OP4B5zSiqG82q8X7nYVkcID+2F/3ekPLMOlWn53OrcdfKKDIcqavoTkQJefc2\nggXU3WgVCxGki/qCm+e5cZ1Cpl/ykSLOT8dWMEzDd12kin66zJ3KYz9F2Q5kQTh4\nKRAChnBBoEqzOfENHEAaHALiXOlVSy61VcLbtvskRMMwBtsydlnd9n/HGnktgrid\n3Ca0z5wBTHWjAOBvCKxKJuDa+jmyHEnpcQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\nAQBXvmyPWgXhC26cHYJBgQqj57dZ+n7p00kM1J+27oDMjGmbmX+XIKXLWazw/rG3\ngDjw9MXI2tVCrQMX0ohjphaULXhb/VBUPDOiW+k7C6AB3nZySFRflcR3cM4f83zF\nMoBd0549h5Red4p72FeOKNJRTN8YO4ooH9YNh5g0FQkgqn7fV9w2CNlomeKIW9zP\nm8tjFw0cJUk2wEYBVl8O7ko5rgNlzhkLoZkMvJhKa99AQJA6MAdyoLl1lv56Kq4X\njk+mMEiz9SaInp+ILQ1uQxZEwuC7DoGRW76rV4Fnie6+DLft4WKZfX1497mx8NV3\noR0abutJaKnCj07dwRu4/EsK\n-----END CERTIFICATE-----",
|
||||||
|
"attr_first_name": "first_name",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SOCIAL_AUTH_SAML_CALLBACK_URL": "CALLBACK_URL",
|
||||||
|
"AUTH_LDAP_1_SERVER_URI": "SERVER_URI",
|
||||||
|
"AUTH_LDAP_1_BIND_DN": "BIND_DN",
|
||||||
|
"AUTH_LDAP_1_BIND_PASSWORD": "BIND_PASSWORD",
|
||||||
|
"AUTH_LDAP_1_GROUP_SEARCH": ["GROUP_SEARCH"],
|
||||||
|
"AUTH_LDAP_1_GROUP_TYPE": "string object",
|
||||||
|
"AUTH_LDAP_1_GROUP_TYPE_PARAMS": {"member_attr": "member", "name_attr": "cn"},
|
||||||
|
"AUTH_LDAP_1_USER_DN_TEMPLATE": "USER_DN_TEMPLATE",
|
||||||
|
"AUTH_LDAP_1_USER_SEARCH": ["USER_SEARCH"],
|
||||||
|
"AUTH_LDAP_1_USER_ATTR_MAP": {
|
||||||
|
"email": "email",
|
||||||
|
"last_name": "last_name",
|
||||||
|
"first_name": "first_name",
|
||||||
|
},
|
||||||
|
"AUTH_LDAP_1_CONNECTION_OPTIONS": {},
|
||||||
|
"AUTH_LDAP_1_START_TLS": None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(**settings_dict)
|
||||||
|
class TestDumpAuthConfigCommand(TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super().setUp()
|
||||||
|
self.expected_config = [
|
||||||
|
{
|
||||||
|
"type": "awx.authentication.authenticator_plugins.saml",
|
||||||
|
"name": "Keycloak",
|
||||||
|
"enabled": True,
|
||||||
|
"create_objects": True,
|
||||||
|
"users_unique": False,
|
||||||
|
"remove_users": True,
|
||||||
|
"configuration": {
|
||||||
|
"SP_ENTITY_ID": "SP_ENTITY_ID",
|
||||||
|
"SP_PUBLIC_CERT": "SP_PUBLIC_CERT",
|
||||||
|
"SP_PRIVATE_KEY": "SP_PRIVATE_KEY",
|
||||||
|
"ORG_INFO": "ORG_INFO",
|
||||||
|
"TECHNICAL_CONTACT": "TECHNICAL_CONTACT",
|
||||||
|
"SUPPORT_CONTACT": "SUPPORT_CONTACT",
|
||||||
|
"SP_EXTRA": "SP_EXTRA",
|
||||||
|
"SECURITY_CONFIG": "SECURITY_CONFIG",
|
||||||
|
"EXTRA_DATA": "EXTRA_DATA",
|
||||||
|
"ENABLED_IDPS": {
|
||||||
|
"Keycloak": {
|
||||||
|
"attr_last_name": "last_name",
|
||||||
|
"attr_groups": "groups",
|
||||||
|
"attr_email": "email",
|
||||||
|
"attr_user_permanent_id": "name_id",
|
||||||
|
"attr_username": "username",
|
||||||
|
"entity_id": "https://example.com/auth/realms/awx",
|
||||||
|
"url": "https://example.com/auth/realms/awx/protocol/saml",
|
||||||
|
"x509cert": "-----BEGIN CERTIFICATE-----\nMIIDDjCCAfYCCQCPBeVvpo8+VzANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCTkMxDzANBgNVBAcMBkR1cmhhbTEMMAoGA1UECgwDYXd4MQ4w\nDAYDVQQDDAVsb2NhbDAeFw0yNDAxMTgxNDA4MzFaFw0yNTAxMTcxNDA4MzFaMEkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOQzEPMA0GA1UEBwwGRHVyaGFtMQwwCgYD\nVQQKDANhd3gxDjAMBgNVBAMMBWxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAzouj93oyFXsHEABdPESh3CYpp5QJJBM4TLYIIolk6PFOFIVwBuFY\nfExi5w7Hh4A42lPM6RkrT+u3h7LV39H9MRUfqygOSmaxICTOI0sU9ROHc44fWWzN\n756OP4B5zSiqG82q8X7nYVkcID+2F/3ekPLMOlWn53OrcdfKKDIcqavoTkQJefc2\nggXU3WgVCxGki/qCm+e5cZ1Cpl/ykSLOT8dWMEzDd12kin66zJ3KYz9F2Q5kQTh4\nKRAChnBBoEqzOfENHEAaHALiXOlVSy61VcLbtvskRMMwBtsydlnd9n/HGnktgrid\n3Ca0z5wBTHWjAOBvCKxKJuDa+jmyHEnpcQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\nAQBXvmyPWgXhC26cHYJBgQqj57dZ+n7p00kM1J+27oDMjGmbmX+XIKXLWazw/rG3\ngDjw9MXI2tVCrQMX0ohjphaULXhb/VBUPDOiW+k7C6AB3nZySFRflcR3cM4f83zF\nMoBd0549h5Red4p72FeOKNJRTN8YO4ooH9YNh5g0FQkgqn7fV9w2CNlomeKIW9zP\nm8tjFw0cJUk2wEYBVl8O7ko5rgNlzhkLoZkMvJhKa99AQJA6MAdyoLl1lv56Kq4X\njk+mMEiz9SaInp+ILQ1uQxZEwuC7DoGRW76rV4Fnie6+DLft4WKZfX1497mx8NV3\noR0abutJaKnCj07dwRu4/EsK\n-----END CERTIFICATE-----",
|
||||||
|
"attr_first_name": "first_name",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"CALLBACK_URL": "CALLBACK_URL",
|
||||||
|
"IDP_URL": "https://example.com/auth/realms/awx/protocol/saml",
|
||||||
|
"IDP_X509_CERT": "-----BEGIN CERTIFICATE-----\nMIIDDjCCAfYCCQCPBeVvpo8+VzANBgkqhkiG9w0BAQsFADBJMQswCQYDVQQGEwJV\nUzELMAkGA1UECAwCTkMxDzANBgNVBAcMBkR1cmhhbTEMMAoGA1UECgwDYXd4MQ4w\nDAYDVQQDDAVsb2NhbDAeFw0yNDAxMTgxNDA4MzFaFw0yNTAxMTcxNDA4MzFaMEkx\nCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJOQzEPMA0GA1UEBwwGRHVyaGFtMQwwCgYD\nVQQKDANhd3gxDjAMBgNVBAMMBWxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A\nMIIBCgKCAQEAzouj93oyFXsHEABdPESh3CYpp5QJJBM4TLYIIolk6PFOFIVwBuFY\nfExi5w7Hh4A42lPM6RkrT+u3h7LV39H9MRUfqygOSmaxICTOI0sU9ROHc44fWWzN\n756OP4B5zSiqG82q8X7nYVkcID+2F/3ekPLMOlWn53OrcdfKKDIcqavoTkQJefc2\nggXU3WgVCxGki/qCm+e5cZ1Cpl/ykSLOT8dWMEzDd12kin66zJ3KYz9F2Q5kQTh4\nKRAChnBBoEqzOfENHEAaHALiXOlVSy61VcLbtvskRMMwBtsydlnd9n/HGnktgrid\n3Ca0z5wBTHWjAOBvCKxKJuDa+jmyHEnpcQIDAQABMA0GCSqGSIb3DQEBCwUAA4IB\nAQBXvmyPWgXhC26cHYJBgQqj57dZ+n7p00kM1J+27oDMjGmbmX+XIKXLWazw/rG3\ngDjw9MXI2tVCrQMX0ohjphaULXhb/VBUPDOiW+k7C6AB3nZySFRflcR3cM4f83zF\nMoBd0549h5Red4p72FeOKNJRTN8YO4ooH9YNh5g0FQkgqn7fV9w2CNlomeKIW9zP\nm8tjFw0cJUk2wEYBVl8O7ko5rgNlzhkLoZkMvJhKa99AQJA6MAdyoLl1lv56Kq4X\njk+mMEiz9SaInp+ILQ1uQxZEwuC7DoGRW76rV4Fnie6+DLft4WKZfX1497mx8NV3\noR0abutJaKnCj07dwRu4/EsK\n-----END CERTIFICATE-----",
|
||||||
|
"IDP_ENTITY_ID": "https://example.com/auth/realms/awx",
|
||||||
|
"IDP_ATTR_EMAIL": "email",
|
||||||
|
"IDP_GROUPS": "groups",
|
||||||
|
"IDP_ATTR_USERNAME": "username",
|
||||||
|
"IDP_ATTR_LAST_NAME": "last_name",
|
||||||
|
"IDP_ATTR_FIRST_NAME": "first_name",
|
||||||
|
"IDP_ATTR_USER_PERMANENT_ID": "name_id",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "awx.authentication.authenticator_plugins.ldap",
|
||||||
|
"name": "1",
|
||||||
|
"enabled": True,
|
||||||
|
"create_objects": True,
|
||||||
|
"users_unique": False,
|
||||||
|
"remove_users": True,
|
||||||
|
"configuration": {
|
||||||
|
"SERVER_URI": "SERVER_URI",
|
||||||
|
"BIND_DN": "BIND_DN",
|
||||||
|
"BIND_PASSWORD": "BIND_PASSWORD",
|
||||||
|
"CONNECTION_OPTIONS": {},
|
||||||
|
"GROUP_TYPE": "str",
|
||||||
|
"GROUP_TYPE_PARAMS": {"member_attr": "member", "name_attr": "cn"},
|
||||||
|
"GROUP_SEARCH": ["GROUP_SEARCH"],
|
||||||
|
"START_TLS": None,
|
||||||
|
"USER_DN_TEMPLATE": "USER_DN_TEMPLATE",
|
||||||
|
"USER_ATTR_MAP": {"email": "email", "last_name": "last_name", "first_name": "first_name"},
|
||||||
|
"USER_SEARCH": ["USER_SEARCH"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
def test_json_returned_from_cmd(self):
|
||||||
|
output = StringIO()
|
||||||
|
call_command("dump_auth_config", stdout=output)
|
||||||
|
assert json.loads(output.getvalue()) == self.expected_config
|
||||||
Reference in New Issue
Block a user