You can configure different SSO backends with remoteAuth.
The implementation is based on Python Social Auth.
Depending on the chosen backend you need to configure different parameters.
You can leverage the extraConfig value in conjunction with remoteAuth.
By default the users do not have any permission after logging in.
Using custom auth pipelines you can assign groups based on the roles supplied by the oauth provider.
remoteAuth:
enabled: true
backends:
- social_core.backends.keycloak.KeycloakOAuth2
autoCreateUser: true
extraConfig:
- secret:
secretName: keycloak-client
- values:
SOCIAL_AUTH_PIPELINE:
[
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.user.get_username",
"social_core.pipeline.social_auth.associate_by_email",
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"netbox.authentication.user_default_groups_handler",
"social_core.pipeline.social_auth.load_extra_data",
"social_core.pipeline.user.user_details",
"netbox.sso_pipeline_roles.set_role",
]
extraVolumes:
- name: sso-pipeline-roles
configMap:
name: sso-pipeline-roles
extraVolumeMounts:
- name: sso-pipeline-roles
mountPath: /opt/netbox/netbox/netbox/sso_pipeline_roles.py
subPath: sso_pipeline_roles.py
readOnly: trueAdditional resources are necessary (please note that the client ID is necessary in the custom pipeline script):
apiVersion: v1
kind: Secret
metadata:
name: keycloak-client
namespace: netbox
type: Opaque
data:
oidc-keycloak.yaml: |
SOCIAL_AUTH_KEYCLOAK_KEY: <OAUTH_CLIENT_ID>
SOCIAL_AUTH_KEYCLOAK_SECRET: <OAUTH_CLIENT_SECRET>
SOCIAL_AUTH_KEYCLOAK_PUBLIC_KEY: MIIB...AB
SOCIAL_AUTH_KEYCLOAK_AUTHORIZATION_URL: "https://keycloak.example.com/auth/realms/master/protocol/openid-connect/auth"
SOCIAL_AUTH_KEYCLOAK_ACCESS_TOKEN_URL: "https://keycloak.example.com/auth/realms/master/protocol/openid-connect/token"
SOCIAL_AUTH_JSONFIELD_ENABLED: true
---
apiVersion: v1
kind: ConfigMap
metadata:
name: sso-pipeline-roles
namespace: netbox
data:
sso_pipeline_roles.py: |
from netbox.authentication import Group
def set_role(response, user, backend, *args, **kwargs):
client_id = '<OAUTH_CLIENT_ID>'
roles = []
try:
roles = response['resource_access'][client_id]['roles']
except KeyError:
pass
user.is_staff = ('admin' in roles)
user.is_superuser = ('superuser' in roles)
user.save()
groups = Group.objects.all()
for group in groups:
try:
if group.name in roles:
group.users.add(user)
else:
group.users.remove(user)
except Group.DoesNotExist:
continueNote
A hardcoded custom audience mapper is required on Keycloak.
For the audience name to be in the token, enter the Client ID in the Included Custom Audience field instead of the Included Client Audience field.
Refer to the Keycloak usage materials:
remoteAuth:
enabled: true
backends:
- social_core.backends.gitlab.GitLabOAuth2
autoCreateUser: true
extraConfig:
- secret:
secretName: gitlab-client
- values:
SOCIAL_AUTH_PIPELINE:
[
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.user.get_username",
"social_core.pipeline.social_auth.associate_by_email",
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"netbox.authentication.user_default_groups_handler",
"social_core.pipeline.social_auth.load_extra_data",
"social_core.pipeline.user.user_details",
"netbox.sso_pipeline_roles.set_role",
]
extraVolumes:
- name: sso-pipeline-roles
configMap:
name: sso-pipeline-roles
extraVolumeMounts:
- name: sso-pipeline-roles
mountPath: /opt/netbox/netbox/netbox/sso_pipeline_roles.py
subPath: sso_pipeline_roles.py
readOnly: trueAdditional resources are necessary (please note that the client ID is necessary in the custom pipeline script):
apiVersion: v1
kind: Secret
metadata:
name: gitlab-client
namespace: netbox
type: Opaque
stringData:
oidc-gitlab.yaml: |
SOCIAL_AUTH_GITLAB_API_URL: https://git.example.com
SOCIAL_AUTH_GITLAB_AUTHORIZATION_URL: https://git.example.com/oauth/authorize
SOCIAL_AUTH_GITLAB_ACCESS_TOKEN_URL: https://git.example.com/oauth/token
SOCIAL_AUTH_GITLAB_KEY: <OAUTH_CLIENT_ID>
SOCIAL_AUTH_GITLAB_SECRET: <OAUTH_CLIENT_SECRET>
SOCIAL_AUTH_GITLAB_SCOPE: ['read_user', 'openid']
---
apiVersion: v1
kind: ConfigMap
metadata:
name: sso-pipeline-roles
namespace: netbox
data:
sso_pipeline_roles.py: |
from netbox.authentication import Group
import jwt
from jwt import PyJWKClient
def set_role(response, user, backend, *args, **kwargs):
jwks_client = PyJWKClient("https://git.example.com/oauth/discovery/keys")
signing_key = jwks_client.get_signing_key_from_jwt(response['id_token'])
decoded = jwt.decode(
response['id_token'],
signing_key.key,
algorithms=["RS256"],
audience="<OAUTH_CLIENT_ID>",
)
roles = []
try:
roles = decoded.get('groups_direct')
except KeyError:
pass
user.is_staff = ('network' in roles)
user.is_superuser = ('network' in roles)
user.save()
groups = Group.objects.all()
for group in groups:
try:
if group.name in roles:
group.users.add(user)
else:
group.users.remove(user)
except Group.DoesNotExist:
continueIn order to enable LDAP authentication, please carry out the following steps:
- Configure the
remoteAuthsettings to enable the LDAP backend (see below) - Make sure you set all of the
remoteAuth.ldapsettings shown in thevalues.yamlfile
For example:
remoteAuth:
enabled: true
backends:
- netbox.authentication.LDAPBackend
ldap:
serverUri: 'ldap://domain.com'
startTls: true
ignoreCertErrors: true
bindDn: ''
bindPassword: ''
# and ALL the other remoteAuth.ldap.* settings from values.yamlNote: in order to use anonymous LDAP binding set bindDn and bindPassword
to an empty string as in the example above.
If you need to specify your own CA certificate, follow the instructions below.
In your values.yaml file define your CA certificate content in caCertData:
ldap:
serverUri: 'ldap://domain.com'
startTls: true
ignoreCertErrors: false
caCertData: |
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----