Skip to content

Commit 2d83cec

Browse files
newswangerdironfroggybmclaughlinrochacbruno
authored
Backport lots of 4.4 things (#954)
* Allow configuration of KEYCLOAK_HOST_LOOPBACK env var (#942) No-Issue (cherry picked from commit b21faf4) * Add configuration for API access logging to dev environment (#946) * Add configuration for API access logging to dev environment No-Issue * Move configuration to dev/Dockerfile.base No-Issue (cherry picked from commit 858f53e) * Pass .compose.env variables to the containers (#947) docker compose allows `env_file` to be a list of .env files those files are loaded in order. It makes easier to have custom local settings. Ex: ``` PULP_GALAXY_ENABLE_API_ACCESS_LOG=true ``` will enable logs to be written to `/var/log/galaxy_api_access.log` No-Issue (cherry picked from commit 0edf87f) * Add controllers endpoint for listing connected controllers (#941) * Add controllers endpoint for listing connected controllers Issue: AAH-888 (cherry picked from commit f2d4092) * Attempt to fix Keycloak conditional settings using Dynaconf Hooks (#945) KEYCLOAK settings was not being loaded from /etc/pulp/settings.py Dynaconf hooks are available only on 3.1.6 Issue: AAH-915 (cherry picked from commit 0bf124a) * Enable keycloak SSO for podman login (#949) * Enable keycloak SSO for podman login (cherry picked from commit 9580c5d) Co-authored-by: ironfroggy <cspealma@redhat.com> Co-authored-by: Brian McLaughlin <bmclaugh@redhat.com> Co-authored-by: Bruno Rocha <rochacbruno@users.noreply.github.com>
1 parent 5f7ffbb commit 2d83cec

22 files changed

+505
-268
lines changed

.compose.env.example

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,7 @@ LOCK_REQUIREMENTS=1
3939
WAIT_FOR_MIGRATIONS=1
4040

4141
# Add variables keycloak integration
42-
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY="keycloak-public-key"
42+
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY="keycloak-public-key"
43+
44+
# Define if your keycloak environment is not running on localhost
45+
KEYCLOAK_HOST_LOOPBACK="192.168.1.14"

CHANGES/888.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add CONNECTED_ANSIBLE_CONTROLLERS setting which enables users to specify a list of controller instances that they wish to have galaxy ng connect to.

CHANGES/915.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix keycloak setting not being loaded from /etc/pulp/settings.py

CHANGES/916.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Enable keycloak authentication using username and password for podman login.

dev/Dockerfile.base

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,9 @@ RUN set -ex; \
9494
&& mv /app/docker/entrypoint.sh /entrypoint.sh \
9595
&& mv /app/ansible.cfg /etc/ansible/ansible.cfg \
9696
&& mv /app/docker/bin/* /usr/local/bin \
97+
&& touch /var/log/galaxy_api_access.log \
98+
&& chmod 0644 /var/log/galaxy_api_access.log \
99+
&& chown galaxy:galaxy /var/log/galaxy_api_access.log \
97100
&& mkdir -p /etc/pulp/certs/ \
98101
&& echo "DNmNdwgyZugTax9S64J0FITTr9IHPxbuoF1F1CGPr68=" > /etc/pulp/certs/database_fields.symmetric.key
99102

dev/insights/docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ services:
55
api:
66
env_file:
77
- './insights/galaxy_ng.env'
8+
- '../.compose.env'
89
worker:
910
env_file:
1011
- './insights/galaxy_ng.env'
12+
- '../.compose.env'
1113
content-app:
1214
env_file:
1315
- './insights/galaxy_ng.env'
16+
- '../.compose.env'

dev/standalone-keycloak/docker-compose.yml

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,20 @@ services:
55
api:
66
env_file:
77
- './standalone-keycloak/galaxy_ng.env'
8-
environment:
9-
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: ${SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY}
8+
- '../.compose.env'
109
worker:
1110
env_file:
1211
- './standalone-keycloak/galaxy_ng.env'
13-
environment:
14-
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: ${SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY}
12+
- '../.compose.env'
1513
content-app:
1614
env_file:
1715
- './standalone-keycloak/galaxy_ng.env'
18-
environment:
19-
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: ${SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY}
20-
16+
- '../.compose.env'
2117
keycloak:
2218
image: quay.io/keycloak/keycloak:latest
2319
env_file:
2420
- './standalone-keycloak/keycloak.env'
21+
- '../.compose.env'
2522
ports:
2623
- 8080:8080
2724
depends_on:
@@ -34,6 +31,7 @@ services:
3431
- kc_pg_data:/var/lib/postgresql/data
3532
env_file:
3633
- './standalone-keycloak/kc-postgres.env'
34+
- '../.compose.env'
3735

3836
ldap:
3937
image: "rroemhild/test-openldap"

dev/standalone-keycloak/galaxy_ng.env

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ PULP_TOKEN_SIGNATURE_ALGORITHM=ES256
2323
PULP_PUBLIC_KEY_PATH=/src/galaxy_ng/dev/common/container_auth_public_key.pem
2424
PULP_PRIVATE_KEY_PATH=/src/galaxy_ng/dev/common/container_auth_private_key.pem
2525

26-
SOCIAL_AUTH_KEYCLOAK_KEY=automation-hub
27-
SOCIAL_AUTH_KEYCLOAK_SECRET=REALLYWELLKEPTSECRET
28-
SOCIAL_AUTH_LOGIN_REDIRECT_URL=http://localhost:8002
29-
KEYCLOAK_PROTOCOL=http
30-
KEYCLOAK_HOST=keycloak
31-
KEYCLOAK_HOST_LOOPBACK=0.0.0.0
32-
KEYCLOAK_PORT=8080
33-
KEYCLOAK_REALM=aap
26+
PULP_SOCIAL_AUTH_KEYCLOAK_KEY=automation-hub
27+
PULP_SOCIAL_AUTH_KEYCLOAK_SECRET=REALLYWELLKEPTSECRET
28+
PULP_SOCIAL_AUTH_LOGIN_REDIRECT_URL=http://localhost:8002
29+
PULP_KEYCLOAK_PROTOCOL=http
30+
PULP_KEYCLOAK_HOST=keycloak
31+
PULP_KEYCLOAK_HOST_LOOPBACK=0.0.0.0
32+
PULP_KEYCLOAK_PORT=8080
33+
PULP_KEYCLOAK_REALM=aap

dev/standalone-keycloak/keycloak-playbook.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@
5252
consent_required: no
5353
standard_flow_enabled: yes
5454
implicit_flow_enabled: no
55-
direct_access_grants_enabled: no
56-
service_accounts_enabled: no
55+
direct_access_grants_enabled: yes
56+
service_accounts_enabled: yes
5757
authorization_services_enabled: no
5858
public_client: no
5959
frontchannel_logout: no

dev/standalone/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ RUN set -ex; \
1111

1212
USER root
1313

14-
RUN dnf install -y gettext
14+
RUN dnf install -y gettext;
1515

1616
USER galaxy

dev/standalone/docker-compose.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ services:
55
api:
66
env_file:
77
- './standalone/galaxy_ng.env'
8+
- '../.compose.env'
89
worker:
910
env_file:
1011
- './standalone/galaxy_ng.env'
12+
- '../.compose.env'
1113
content-app:
1214
env_file:
1315
- './standalone/galaxy_ng.env'
16+
- '../.compose.env'

galaxy_ng/app/api/ui/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@
125125

126126
path('auth/', include(auth_views)),
127127
path('feature-flags/', views.FeatureFlagsView.as_view(), name='feature-flags'),
128+
path('controllers/', views.ControllerListView.as_view(), name='controllers'),
128129
path('groups/', include(group_paths)),
129130
path(
130131
'repo/<str:path>/',

galaxy_ng/app/api/ui/views/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@
44
)
55
from .feature_flags import FeatureFlagsView
66

7+
from .controller import ControllerListView
8+
79
__all__ = (
810
# auth
911
"LoginView",
1012
"LogoutView",
1113

1214
# feature_flags
1315
"FeatureFlagsView",
16+
17+
# controller
18+
"ControllerListView",
1419
)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from django.conf import settings
2+
from rest_framework.permissions import IsAuthenticated
3+
4+
from galaxy_ng.app.api import base as api_base
5+
6+
7+
class ControllerListView(api_base.APIView):
8+
permission_classes = [IsAuthenticated]
9+
10+
# Returns a paginated list. This will make this easier to upgrade to a
11+
# database setting down the line.
12+
def get(self, request, *args, **kwargs):
13+
host_filter = request.GET.get("host", None)
14+
host_icontains_filter = request.GET.get("host__icontains", None)
15+
16+
controllers = []
17+
for controller in settings.CONNECTED_ANSIBLE_CONTROLLERS:
18+
if host_filter and controller != host_filter:
19+
continue
20+
21+
if host_icontains_filter and host_icontains_filter.lower() not in controller.lower():
22+
continue
23+
24+
controllers.append({"host": controller})
25+
paginator = self.pagination_class()
26+
page = paginator.paginate_queryset(controllers, request, view=self)
27+
28+
return paginator.get_paginated_response(page)

galaxy_ng/app/auth/keycloak.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
from requests import post as requests_post
2+
3+
from django.conf import settings
4+
5+
from rest_framework.authentication import BasicAuthentication
6+
7+
from rest_framework import status as http_code
8+
from rest_framework import exceptions
9+
10+
from social_django.utils import load_strategy
11+
from social_core.backends.keycloak import KeycloakOAuth2
12+
13+
from gettext import gettext as _
14+
15+
16+
class KeycloakBasicAuth(BasicAuthentication):
17+
def authenticate_credentials(self, userid, password, request=None):
18+
payload = {
19+
'client_id': settings.SOCIAL_AUTH_KEYCLOAK_KEY,
20+
'client_secret': settings.SOCIAL_AUTH_KEYCLOAK_SECRET,
21+
'grant_type': 'password',
22+
'scope': 'openid',
23+
'username': userid,
24+
'password': password
25+
}
26+
headers = {
27+
"Content-Type": "application/x-www-form-urlencoded",
28+
}
29+
30+
response = requests_post(
31+
url=settings.SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL,
32+
headers=headers,
33+
data=payload
34+
)
35+
36+
if response.status_code == http_code.HTTP_200_OK:
37+
38+
# load social auth django strategy
39+
strategy = load_strategy(request)
40+
backend = KeycloakOAuth2(strategy)
41+
42+
token_data = backend.user_data(response.json()['access_token'])
43+
44+
# The django social auth strategy uses data from the JWT token in the KeycloackOAuth2
45+
# backend to create a new user and update it with the data from the token. This
46+
# should return a django user instance.
47+
user = strategy.authenticate(backend, response=token_data)
48+
49+
if user is None:
50+
raise exceptions.AuthenticationFailed(_("Authentication failed."))
51+
52+
return (user, None)
53+
54+
else:
55+
# If keycloak basic auth fails, try regular basic auth.
56+
return super().authenticate_credentials(userid, password, request)

0 commit comments

Comments
 (0)