Open einermart opened 1 year ago
Hi, can you provide more information about what you are trying to accomplish? e.g. are you attempting to use the keycloak module within AWX?
more information about the specific ENVs would be helpful
Hello, I sure can.
I am trying to configure the following OIDC ENVs using extra_settings:
SOCIAL_AUTH_OIDC_KEY
SOCIAL_AUTH_OIDC_SECRET
SOCIAL_AUTH_OIDC_OIDC_ENDPOINT
I want to be able to set those ENVs referencing an existing secret within my namespace.
extra_settings:
- name: SOCIAL_AUTH_OIDC_KEY
valueFrom:
secretKeyRef:
name: awx-operator-keycloak-credentials
key: client-id
- name: SOCIAL_AUTH_OIDC_SECRET
valueFrom:
secretKeyRef:
name: awx-operator-keycloak-credentials
key: client-secret
- name: SOCIAL_AUTH_OIDC_OIDC_ENDPOINT
valueFrom:
secretKeyRef:
name: awx-operator-keycloak-credentials
key: realm_url
Using the method above fails due to valueFrom
being an unrecognized field. I hope that provides a bit more information.
Thank you
+1
Currently, LDAP seems to be the only authentication backend that's capable of loading sensitive information (i.e. LDAP bind password) from a k8s secret, thanks to load_ldap_password_secret.yml.
To enable a "social" auth provider (GitHub, AzureAD...etc), one has to initialize an AWX instance with a local admin, use the local admin account to login, and manually insert provider's secrets (OAuth secrets, SAML certificates...) on a webpage. I want to be able to control auth provider configuration in an infrastructure-as-code way.
this should be very useful
Could someone point me to how I might begin to implement this feature? I'm happy to take a crack at it.
The keys and values that passed over extra_settings
will be embedded to settings.py
as a part of Python code. Currently there is no handy way to pass values from Secrets to extra_settings
.
As a workaround, this is a bit tricky way, but you can add environment variable from Secrets, and pass extra_settings
with the code that reads values from environment variables.
---
apiVersion: awx.ansible.com/v1beta1
kind: AWX
metadata:
name: awx
spec:
...
task_extra_env: |
- name: SOCIAL_AUTH_AZUREAD_OAUTH2_KEY
valueFrom:
secretKeyRef:
name: awx-azuread-oauth2-secret
key: key
- name: SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET
valueFrom:
secretKeyRef:
name: awx-azuread-oauth2-secret
key: secret
web_extra_env: |
- name: SOCIAL_AUTH_AZUREAD_OAUTH2_KEY
valueFrom:
secretKeyRef:
name: awx-azuread-oauth2-secret
key: key
- name: SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET
valueFrom:
secretKeyRef:
name: awx-azuread-oauth2-secret
key: secret
extra_settings:
- setting: SOCIAL_AUTH_AZUREAD_OAUTH2_KEY
value: 'os.getenv("SOCIAL_AUTH_AZUREAD_OAUTH2_KEY")'
- setting: SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET
value: 'os.getenv("SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET")'
You can see the environment variables SOCIAL_AUTH_AZUREAD_OAUTH2_KEY
and SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET
have the actual values and the settings in settings.py
are configured to read values from environment variables.
$ kubectl -n awx exec -it deployment/awx-web -c awx-web -- env | grep SOCIAL_AUTH_AZUREAD
SOCIAL_AUTH_AZUREAD_OAUTH2_KEY=****************
SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET=****************
$ kubectl -n awx exec -it deployment/awx-web -c awx-web -- cat /etc/tower/settings.py
import os
import socket
...
SOCIAL_AUTH_AZUREAD_OAUTH2_KEY = os.getenv("SOCIAL_AUTH_AZUREAD_OAUTH2_KEY")
SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET = os.getenv("SOCIAL_AUTH_AZUREAD_OAUTH2_SECRET")
...
@kurokobo Your workaround does work for string values but does not work for json values. It also appears that you cannot inject the python code for os.getenv("ENV_VARIABLE")
in to a json value as the jinja2 templating it putting quotes around it causing it to be read as a string instead of being executed.
Any ideas on how to handle this? Or would that just require code changes to be made to support that functionality?
@tylergmuir Can you provide some example keys and values that you want to inject? In particular, how would you like to use Jinja2?
@kurokobo The specific use-case I had was with the SOCIAL_AUTH_SAML_ENABLED_IDPS
setting. It takes in a json value like this:
{
"saml_ms_adfs": {
"x509cert": "${SAML_IDP_SIGNING_CERT}",
"attr_last_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"attr_first_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"attr_email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"attr_username": "name_id",
"attr_user_permanent_id": "name_id",
"entity_id": "https://adfs.domain.com/adfs/services/trust",
"url": "https://adfs.domain.com/adfs/ls"
}
}
The only thing that I would require to be passed as a secret is the x509cert
value, but it is workable if I had to pass the entire value as a secret. But if you try subbing "${SAML_IDP_SIGNING_CERT}"
with os.getenv("SOME_ENV_VAR")
it gets surrounded with quotes like it is a string. Alternatively, if you pass the entire value as a env var, it ends up with a parsing error as it is collected a one giant string value.
This could probably be solved by using the json
python module, but without making upstream modification to include additional modules for parsing the settings file, I don't see a way to handle this currently.
@tylergmuir
It takes in a json value like this
Not JSON, but Dict in python. so you dont't need quoting os.getenv("SOME_ENV_VAR")
.
I can't fully test this since I don't have any labs for SAML auth, but I can deploy AWX without any errors with SAML configuration through extra_settings
with the cert from secret.
I think the following two are important:
# Create a secret based on a literal string
# because it contains newlines and headers/footers when created based on a PEM file
$ kubectl -n awx create secret generic awx-saml-idp-signing-cert --from-literal=x509cert=MIIDZTCCAk2gAwIB................8AL9sqeB6xGPxz26
spec:
...
# Define env SAML_IDP_SIGNING_CERT for task and web pod
task_extra_env: |
- name: SAML_IDP_SIGNING_CERT
valueFrom:
secretKeyRef:
name: awx-saml-idp-signing-cert
key: x509cert
web_extra_env: |
- name: SAML_IDP_SIGNING_CERT
valueFrom:
secretKeyRef:
name: awx-saml-idp-signing-cert
key: x509cert
extra_settings:
- setting: SOCIAL_AUTH_SAML_ENABLED_IDPS
# Define value as multiline strings with 2 spaces indentation (by "|2")
# And pass the actual value with "6" spaces indentation
# to add 4 leading spaces for each lines to keep indentation in ConfigMap correctly
value: |2
{
"saml_ms_adfs": {
"x509cert": os.getenv("SAML_IDP_SIGNING_CERT"),
"attr_last_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname",
"attr_first_name": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",
"attr_email": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress",
"attr_username": "name_id",
"attr_user_permanent_id": "name_id",
"entity_id": "https://adfs.domain.com/adfs/services/trust",
"url": "https://adfs.domain.com/adfs/ls"
}
}
Result:
If you want the contents of the secret to be the PEM file including newlines and headers and footers, you will need to format os.getenv
with replace
or similar:
"x509cert": os.getenv("SAML_IDP_SIGNING_CERT").replace("\n", "").replace("-----BEGIN CERTIFICATE-----", "").replace("-----END CERTIFICATE----", ""),
@kurokobo That worked perfectly! Since it doesn't seem like this issue has made any progress and is almost a year old, I think it would be good to open a PR with your examples to provide some documentation for others without having to read through all of the comments in the issue. I would be happy to write that up, but I don't want to take credit for your work, so if you would like to do it instead I am good with that too.
Thanks again!
@tylergmuir
I think it would be good to open a PR with your examples to provide some documentation for others without having to read through all of the comments in the issue. I would be happy to write that up, but I don't want to take credit for your work, so if you would like to do it instead I am good with that too.
Thanks for your concern, if you are interested in becoming a contributor, I would love to have you create a PR for the community. I will review it if needed 😃 I was thinking of adding it to the tips section of my guide, but if it is covered in the official documentation, so much the better.
Please confirm the following
Feature Summary
I am trying to setup Keycloak authentication and I would like to inject the different ENVs needed from a secret. Currently extra_settings does not allow to inject envs from secrets. This would be a great feature to add.
Thank you