Skip to content

Commit

Permalink
Backport lots of 4.4 things (#954)
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
Co-authored-by: Brian McLaughlin <[email protected]>
Co-authored-by: Bruno Rocha <[email protected]>
  • Loading branch information
4 people authored Sep 10, 2021
1 parent 5f7ffbb commit 2d83cec
Show file tree
Hide file tree
Showing 22 changed files with 505 additions and 268 deletions.
5 changes: 4 additions & 1 deletion .compose.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ LOCK_REQUIREMENTS=1
WAIT_FOR_MIGRATIONS=1

# Add variables keycloak integration
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY="keycloak-public-key"
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY="keycloak-public-key"

# Define if your keycloak environment is not running on localhost
KEYCLOAK_HOST_LOOPBACK="192.168.1.14"
1 change: 1 addition & 0 deletions CHANGES/888.feature
Original file line number Diff line number Diff line change
@@ -0,0 +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.
1 change: 1 addition & 0 deletions CHANGES/915.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix keycloak setting not being loaded from /etc/pulp/settings.py
1 change: 1 addition & 0 deletions CHANGES/916.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Enable keycloak authentication using username and password for podman login.
3 changes: 3 additions & 0 deletions dev/Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ RUN set -ex; \
&& mv /app/docker/entrypoint.sh /entrypoint.sh \
&& mv /app/ansible.cfg /etc/ansible/ansible.cfg \
&& mv /app/docker/bin/* /usr/local/bin \
&& touch /var/log/galaxy_api_access.log \
&& chmod 0644 /var/log/galaxy_api_access.log \
&& chown galaxy:galaxy /var/log/galaxy_api_access.log \
&& mkdir -p /etc/pulp/certs/ \
&& echo "DNmNdwgyZugTax9S64J0FITTr9IHPxbuoF1F1CGPr68=" > /etc/pulp/certs/database_fields.symmetric.key

Expand Down
3 changes: 3 additions & 0 deletions dev/insights/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ services:
api:
env_file:
- './insights/galaxy_ng.env'
- '../.compose.env'
worker:
env_file:
- './insights/galaxy_ng.env'
- '../.compose.env'
content-app:
env_file:
- './insights/galaxy_ng.env'
- '../.compose.env'
12 changes: 5 additions & 7 deletions dev/standalone-keycloak/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@ services:
api:
env_file:
- './standalone-keycloak/galaxy_ng.env'
environment:
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: ${SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY}
- '../.compose.env'
worker:
env_file:
- './standalone-keycloak/galaxy_ng.env'
environment:
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: ${SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY}
- '../.compose.env'
content-app:
env_file:
- './standalone-keycloak/galaxy_ng.env'
environment:
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: ${SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY}

- '../.compose.env'
keycloak:
image: quay.io/keycloak/keycloak:latest
env_file:
- './standalone-keycloak/keycloak.env'
- '../.compose.env'
ports:
- 8080:8080
depends_on:
Expand All @@ -34,6 +31,7 @@ services:
- kc_pg_data:/var/lib/postgresql/data
env_file:
- './standalone-keycloak/kc-postgres.env'
- '../.compose.env'

ldap:
image: "rroemhild/test-openldap"
Expand Down
16 changes: 8 additions & 8 deletions dev/standalone-keycloak/galaxy_ng.env
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ PULP_TOKEN_SIGNATURE_ALGORITHM=ES256
PULP_PUBLIC_KEY_PATH=/src/galaxy_ng/dev/common/container_auth_public_key.pem
PULP_PRIVATE_KEY_PATH=/src/galaxy_ng/dev/common/container_auth_private_key.pem

SOCIAL_AUTH_KEYCLOAK_KEY=automation-hub
SOCIAL_AUTH_KEYCLOAK_SECRET=REALLYWELLKEPTSECRET
SOCIAL_AUTH_LOGIN_REDIRECT_URL=http://localhost:8002
KEYCLOAK_PROTOCOL=http
KEYCLOAK_HOST=keycloak
KEYCLOAK_HOST_LOOPBACK=0.0.0.0
KEYCLOAK_PORT=8080
KEYCLOAK_REALM=aap
PULP_SOCIAL_AUTH_KEYCLOAK_KEY=automation-hub
PULP_SOCIAL_AUTH_KEYCLOAK_SECRET=REALLYWELLKEPTSECRET
PULP_SOCIAL_AUTH_LOGIN_REDIRECT_URL=http://localhost:8002
PULP_KEYCLOAK_PROTOCOL=http
PULP_KEYCLOAK_HOST=keycloak
PULP_KEYCLOAK_HOST_LOOPBACK=0.0.0.0
PULP_KEYCLOAK_PORT=8080
PULP_KEYCLOAK_REALM=aap
4 changes: 2 additions & 2 deletions dev/standalone-keycloak/keycloak-playbook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@
consent_required: no
standard_flow_enabled: yes
implicit_flow_enabled: no
direct_access_grants_enabled: no
service_accounts_enabled: no
direct_access_grants_enabled: yes
service_accounts_enabled: yes
authorization_services_enabled: no
public_client: no
frontchannel_logout: no
Expand Down
2 changes: 1 addition & 1 deletion dev/standalone/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ RUN set -ex; \

USER root

RUN dnf install -y gettext
RUN dnf install -y gettext;

USER galaxy
3 changes: 3 additions & 0 deletions dev/standalone/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ services:
api:
env_file:
- './standalone/galaxy_ng.env'
- '../.compose.env'
worker:
env_file:
- './standalone/galaxy_ng.env'
- '../.compose.env'
content-app:
env_file:
- './standalone/galaxy_ng.env'
- '../.compose.env'
1 change: 1 addition & 0 deletions galaxy_ng/app/api/ui/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@

path('auth/', include(auth_views)),
path('feature-flags/', views.FeatureFlagsView.as_view(), name='feature-flags'),
path('controllers/', views.ControllerListView.as_view(), name='controllers'),
path('groups/', include(group_paths)),
path(
'repo/<str:path>/',
Expand Down
5 changes: 5 additions & 0 deletions galaxy_ng/app/api/ui/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
)
from .feature_flags import FeatureFlagsView

from .controller import ControllerListView

__all__ = (
# auth
"LoginView",
"LogoutView",

# feature_flags
"FeatureFlagsView",

# controller
"ControllerListView",
)
28 changes: 28 additions & 0 deletions galaxy_ng/app/api/ui/views/controller.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from django.conf import settings
from rest_framework.permissions import IsAuthenticated

from galaxy_ng.app.api import base as api_base


class ControllerListView(api_base.APIView):
permission_classes = [IsAuthenticated]

# Returns a paginated list. This will make this easier to upgrade to a
# database setting down the line.
def get(self, request, *args, **kwargs):
host_filter = request.GET.get("host", None)
host_icontains_filter = request.GET.get("host__icontains", None)

controllers = []
for controller in settings.CONNECTED_ANSIBLE_CONTROLLERS:
if host_filter and controller != host_filter:
continue

if host_icontains_filter and host_icontains_filter.lower() not in controller.lower():
continue

controllers.append({"host": controller})
paginator = self.pagination_class()
page = paginator.paginate_queryset(controllers, request, view=self)

return paginator.get_paginated_response(page)
56 changes: 56 additions & 0 deletions galaxy_ng/app/auth/keycloak.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from requests import post as requests_post

from django.conf import settings

from rest_framework.authentication import BasicAuthentication

from rest_framework import status as http_code
from rest_framework import exceptions

from social_django.utils import load_strategy
from social_core.backends.keycloak import KeycloakOAuth2

from gettext import gettext as _


class KeycloakBasicAuth(BasicAuthentication):
def authenticate_credentials(self, userid, password, request=None):
payload = {
'client_id': settings.SOCIAL_AUTH_KEYCLOAK_KEY,
'client_secret': settings.SOCIAL_AUTH_KEYCLOAK_SECRET,
'grant_type': 'password',
'scope': 'openid',
'username': userid,
'password': password
}
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}

response = requests_post(
url=settings.SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL,
headers=headers,
data=payload
)

if response.status_code == http_code.HTTP_200_OK:

# load social auth django strategy
strategy = load_strategy(request)
backend = KeycloakOAuth2(strategy)

token_data = backend.user_data(response.json()['access_token'])

# The django social auth strategy uses data from the JWT token in the KeycloackOAuth2
# backend to create a new user and update it with the data from the token. This
# should return a django user instance.
user = strategy.authenticate(backend, response=token_data)

if user is None:
raise exceptions.AuthenticationFailed(_("Authentication failed."))

return (user, None)

else:
# If keycloak basic auth fails, try regular basic auth.
return super().authenticate_credentials(userid, password, request)
Loading

0 comments on commit 2d83cec

Please sign in to comment.