Skip to content

Commit 67eab54

Browse files
authored
Add management command to dump auth config data to a file (#2082)
* Add management command to dump auth config data to a file https://issues.redhat.com/browse/AAP-19981 No-Issue
1 parent 5d56bdd commit 67eab54

File tree

2 files changed

+226
-0
lines changed

2 files changed

+226
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
import json
2+
import os
3+
import sys
4+
from django.core.management.base import BaseCommand
5+
from django.conf import settings
6+
7+
8+
class Command(BaseCommand):
9+
KEYCLOAK_KEYS = [
10+
"SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL",
11+
"SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL",
12+
"SOCIAL_AUTH_KEYCLOAK_KEY",
13+
"SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY",
14+
"SOCIAL_AUTH_KEYCLOAK_SECRET",
15+
]
16+
17+
LDAP_KEYS = [
18+
"AUTH_LDAP_SERVER_URI",
19+
"AUTH_LDAP_BIND_DN",
20+
"AUTH_LDAP_BIND_PASSWORD",
21+
"AUTH_LDAP_USER_SEARCH_BASE_DN",
22+
"AUTH_LDAP_USER_SEARCH_SCOPE",
23+
"AUTH_LDAP_USER_SEARCH_FILTER",
24+
"AUTH_LDAP_GROUP_SEARCH_BASE_DN",
25+
"AUTH_LDAP_GROUP_SEARCH_SCOPE",
26+
"AUTH_LDAP_GROUP_SEARCH_FILTER",
27+
]
28+
29+
help = "Dump auth config data from database to a JSON file"
30+
31+
def add_arguments(self, parser):
32+
parser.add_argument(
33+
"output_file",
34+
nargs="?",
35+
type=str,
36+
default=None,
37+
help="Output JSON file path",
38+
)
39+
40+
def is_enabled(self, keys):
41+
values = []
42+
for key in keys:
43+
values.append(settings.get(key, default=None))
44+
return all(values)
45+
46+
def post_config_ldap(self):
47+
post_config = {}
48+
# Other required platform params
49+
post_config["USER_ATTR_MAP"] = settings.get("AUTH_LDAP_USER_ATTR_MAP")
50+
post_config["USER_DN_TEMPLATE"] = settings.get("AUTH_LDAP_USER_DN_TEMPLATE")
51+
post_config["GROUP_TYPE_PARAMS"] = settings.get("AUTH_LDAP_GROUP_TYPE_PARAMS")
52+
post_config["CONNECTION_OPTIONS"] = settings.get("AUTH_LDAP_CONNECTION_OPTIONS")
53+
post_config["START_TLS"] = settings.get("AUTH_LDAP_START_TLS")
54+
55+
# Configure USER_SEARCH and GROUP_SEARCH
56+
AUTH_LDAP_USER_SEARCH_BASE_DN = settings.get("AUTH_LDAP_USER_SEARCH_BASE_DN", default=None)
57+
AUTH_LDAP_USER_SEARCH_SCOPE = settings.get("AUTH_LDAP_USER_SEARCH_SCOPE", default=None)
58+
AUTH_LDAP_USER_SEARCH_FILTER = settings.get("AUTH_LDAP_USER_SEARCH_FILTER", default=None)
59+
AUTH_LDAP_GROUP_SEARCH_BASE_DN = settings.get(
60+
"AUTH_LDAP_GROUP_SEARCH_BASE_DN",
61+
default=None
62+
)
63+
AUTH_LDAP_GROUP_SEARCH_SCOPE = settings.get("AUTH_LDAP_GROUP_SEARCH_SCOPE", default=None)
64+
AUTH_LDAP_GROUP_SEARCH_FILTER = settings.get("AUTH_LDAP_GROUP_SEARCH_FILTER", default=None)
65+
66+
post_config["USER_SEARCH"] = [
67+
AUTH_LDAP_USER_SEARCH_BASE_DN,
68+
AUTH_LDAP_USER_SEARCH_SCOPE,
69+
AUTH_LDAP_USER_SEARCH_FILTER,
70+
]
71+
72+
post_config["GROUP_SEARCH"] = [
73+
AUTH_LDAP_GROUP_SEARCH_BASE_DN,
74+
AUTH_LDAP_GROUP_SEARCH_SCOPE,
75+
AUTH_LDAP_GROUP_SEARCH_FILTER,
76+
]
77+
78+
# Configure GROUP_TYPE
79+
post_config["GROUP_TYPE"] = None
80+
AUTH_LDAP_GROUP_TYPE = settings.get("AUTH_LDAP_GROUP_TYPE")
81+
if AUTH_LDAP_GROUP_TYPE:
82+
post_config["GROUP_TYPE"] = type(AUTH_LDAP_GROUP_TYPE).__name__
83+
84+
return post_config
85+
86+
def format_config_data(self, type, keys, prefix):
87+
config = {
88+
"type": f"galaxy.authentication.authenticator_plugins.{type}",
89+
"enabled": self.is_enabled(keys),
90+
"configuration": {},
91+
}
92+
for key in keys:
93+
k = key
94+
if prefix in key:
95+
k = key[len(prefix):]
96+
v = settings.get(key, default=None)
97+
config["configuration"].update({k: v})
98+
99+
# handle post configuration for ldap:
100+
if type == "ldap":
101+
config["configuration"].update(self.post_config_ldap())
102+
103+
return config
104+
105+
def handle(self, *args, **options):
106+
try:
107+
data = []
108+
109+
# Add Keycloak auth config
110+
data.append(
111+
self.format_config_data(
112+
"keycloak",
113+
self.KEYCLOAK_KEYS,
114+
"SOCIAL_AUTH_KEYCLOAK_"),
115+
)
116+
117+
# Add LDAP auth config
118+
data.append(self.format_config_data("ldap", self.LDAP_KEYS, "AUTH_LDAP_"))
119+
120+
# write to file if requested
121+
if options["output_file"]:
122+
# Define the path for the output JSON file
123+
output_file = options["output_file"]
124+
125+
# Ensure the directory exists
126+
os.makedirs(os.path.dirname(output_file), exist_ok=True)
127+
128+
# Write data to the JSON file
129+
with open(output_file, "w") as f:
130+
json.dump(data, f, indent=4)
131+
132+
self.stdout.write(
133+
self.style.SUCCESS(f"Auth config data dumped to {output_file}")
134+
)
135+
else:
136+
self.stdout.write(json.dumps(data))
137+
138+
except Exception as e:
139+
self.stdout.write(self.style.ERROR(f"An error occurred: {str(e)}"))
140+
sys.exit(1)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
from io import StringIO
2+
import json
3+
from django.core.management import call_command
4+
from django.test import TestCase, override_settings
5+
6+
7+
@override_settings(SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL="ACCESS_TOKEN_URL")
8+
@override_settings(SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL="AUTHORIZATION_URL")
9+
@override_settings(SOCIAL_AUTH_KEYCLOAK_KEY="KEY")
10+
@override_settings(SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY="PUBLIC_KEY")
11+
@override_settings(SOCIAL_AUTH_KEYCLOAK_SECRET="SECRET")
12+
@override_settings(AUTH_LDAP_SERVER_URI="SERVER_URI")
13+
@override_settings(AUTH_LDAP_BIND_DN="BIND_DN")
14+
@override_settings(AUTH_LDAP_BIND_PASSWORD="BIND_PASSWORD")
15+
@override_settings(AUTH_LDAP_USER_DN_TEMPLATE="USER_DN_TEMPLATE")
16+
@override_settings(AUTH_LDAP_USER_SEARCH_BASE_DN="USER_SEARCH_BASE_DN")
17+
@override_settings(AUTH_LDAP_USER_SEARCH_SCOPE="USER_SEARCH_SCOPE")
18+
@override_settings(AUTH_LDAP_USER_SEARCH_FILTER="USER_SEARCH_FILTER")
19+
@override_settings(AUTH_LDAP_GROUP_SEARCH_BASE_DN="GROUP_SEARCH_BASE_DN")
20+
@override_settings(AUTH_LDAP_GROUP_SEARCH_SCOPE="GROUP_SEARCH_SCOPE")
21+
@override_settings(AUTH_LDAP_GROUP_SEARCH_FILTER="GROUP_SEARCH_FILTER")
22+
@override_settings(AUTH_LDAP_GROUP_TYPE_PARAMS="GROUP_TYPE_PARAMS")
23+
@override_settings(AUTH_LDAP_USER_ATTR_MAP={
24+
"email": "email",
25+
"last_name": "last_name",
26+
"first_name": "first_name",
27+
})
28+
@override_settings(AUTH_LDAP_CONNECTION_OPTIONS={})
29+
@override_settings(AUTH_LDAP_START_TLS=None)
30+
@override_settings(AUTH_LDAP_GROUP_TYPE="string object")
31+
class TestDumpAuthConfigCommand(TestCase):
32+
def setUp(self):
33+
super().setUp()
34+
self.expected_config = [
35+
{
36+
"type": "galaxy.authentication.authenticator_plugins.keycloak",
37+
"enabled": True,
38+
"configuration": {
39+
"ACCESS_TOKEN_URL": "ACCESS_TOKEN_URL",
40+
"AUTHORIZATION_URL": "AUTHORIZATION_URL",
41+
"KEY": "KEY",
42+
"PUBLIC_KEY": "PUBLIC_KEY",
43+
"SECRET": "SECRET"
44+
}
45+
},
46+
{
47+
"type": "galaxy.authentication.authenticator_plugins.ldap",
48+
"enabled": True,
49+
"configuration": {
50+
"SERVER_URI": "SERVER_URI",
51+
"BIND_DN": "BIND_DN",
52+
"BIND_PASSWORD": "BIND_PASSWORD",
53+
"USER_SEARCH_BASE_DN": "USER_SEARCH_BASE_DN",
54+
"USER_SEARCH_SCOPE": "USER_SEARCH_SCOPE",
55+
"USER_SEARCH_FILTER": "USER_SEARCH_FILTER",
56+
"GROUP_SEARCH_BASE_DN": "GROUP_SEARCH_BASE_DN",
57+
"GROUP_SEARCH_SCOPE": "GROUP_SEARCH_SCOPE",
58+
"GROUP_SEARCH_FILTER": "GROUP_SEARCH_FILTER",
59+
"USER_ATTR_MAP": {
60+
"email": "email",
61+
"last_name": "last_name",
62+
"first_name": "first_name"
63+
},
64+
"USER_DN_TEMPLATE": "USER_DN_TEMPLATE",
65+
"GROUP_TYPE_PARAMS": "GROUP_TYPE_PARAMS",
66+
"CONNECTION_OPTIONS": {},
67+
"START_TLS": None,
68+
"USER_SEARCH": [
69+
"USER_SEARCH_BASE_DN",
70+
"USER_SEARCH_SCOPE",
71+
"USER_SEARCH_FILTER"
72+
],
73+
"GROUP_SEARCH": [
74+
"GROUP_SEARCH_BASE_DN",
75+
"GROUP_SEARCH_SCOPE",
76+
"GROUP_SEARCH_FILTER"
77+
],
78+
"GROUP_TYPE": "str"
79+
}
80+
}
81+
]
82+
83+
def test_json_returned_from_cmd(self):
84+
output = StringIO()
85+
call_command("dump-auth-config", stdout=output)
86+
assert output.getvalue().rstrip() == json.dumps(self.expected_config)

0 commit comments

Comments
 (0)