Skip to content

Instantly share code, notes, and snippets.

@nahun
Last active May 23, 2024 16:55
Show Gist options
  • Save nahun/7863454be9e7b285863a45519804b803 to your computer and use it in GitHub Desktop.
Save nahun/7863454be9e7b285863a45519804b803 to your computer and use it in GitHub Desktop.
NetBox with Okta SSO using OAuth

NetBox with Okta SSO using OAuth

This is an example setup with NetBox using Okta for authentication. It uses the Python Social Auth library that is supported in NetBox starting in v3.1.

See the NetBox docs on SSO.

This is written to support NetBox v3.1.

Okta Setup

An OIDC application is required in Okta.

Settings

General Tab:

  • Client acting on behalf of a user:
    • Authorization Code: checked
    • Refresh Token: checked
    • Implicit (hybrid): checked
    • Allow ID Token Token with implicit grant type: checked
  • Refresh token behavior: Use persistent token
  • Sign-in redirect URI: https:///oauth/complete/okta-oauth2/
  • Login initiated by: Either Okta or App
  • Login flow: Redirect to app to initiate login
  • Initiate login URI: https:///oauth/login/okta-oauth2/

Setup your groups claim type and/or filter to what your environment requires. Below is an example:

  • OpenID Connect ID Token
    • Groups claim type: Filter
    • Groups claim filter: "groups" Starts with ""

The map_groups method in custom_pipeline.py will set the user's groups to what is returned in the "groups" claim. It will overwrite any other groups. The method can be customized to perform whatever action is needed for your environment.

Add config to your configuration.py

The configuration.py provided here is an example of what is needed to setup this authentication. Merge it with your own configuration.py.

Copy Custom Pipeline File

Copy the custom_pipeline.py file to the $INSTALL_ROOT/netbox/netbox/ directory.

Forcing OAuth

If you don't want the login page to show for users at all and redirect them to OAuth immeditately, then the LOGIN_URL parameter in settings.py needs to be modified. Be aware that modifying anything in settings.py will be overwritten during an upgrade. It is not supported by NetBox.

Example: LOGIN_URL = f'/{BASE_PATH}oauth/login/okta-oauth2/'

Restart NetBox

systemctl restart netbox netbox-rq

LOGIN_REQUIRED = True
REMOTE_AUTH_BACKEND = "social_core.backends.okta.OktaOAuth2"
SOCIAL_AUTH_OKTA_OAUTH2_KEY = "<OKTA-CLIENT-ID>"
SOCIAL_AUTH_OKTA_OAUTH2_SECRET = "<OKTA-CLIENT-SECRET>"
SOCIAL_AUTH_OKTA_OAUTH2_API_URL = "https://<OKTA-TENANT>.okta.com/oauth2"
SOCIAL_AUTH_OKTA_OAUTH2_SCOPE = ['openid', 'profile', 'email', 'groups']
# The default pipeline plus the map_groups method
# Pipeline docs: https://python-social-auth.readthedocs.io/en/latest/pipeline.html#authentication-pipeline
SOCIAL_AUTH_PIPELINE = (
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.auth_allowed",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.user.get_username",
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"social_core.pipeline.social_auth.load_extra_data",
"social_core.pipeline.user.user_details",
"netbox.custom_pipeline.map_groups"
)
from django.contrib.auth.models import Group
class AuthFailed(Exception):
pass
# Set NetBox group based on the "groups" claim
def map_groups(response, user, backend, *args, **kwargs):
# Clear out groups when none are assigned in SSO
if not response.get('groups'):
user.groups.clear()
return
for sso_group in response.get('groups', []):
try:
group = Group.objects.get(name=str(sso_group))
except Group.DoesNotExist:
raise AuthFailed(f"Unknown group: {sso_group}")
group.user_set.add(user)
@Arshnika
Copy link

Hi @nahun,

I have been looking for this. However, I followed your instruction, but to no avail!

Does "sso_group" in the above code refer to the configured security group accessing the NetBox Okta app?

FYI, in my setup, we use Active Directory as the Okta backend authenticator.

Thanks.

@nahun
Copy link
Author

nahun commented May 20, 2024

@Arshnika sso_group is coming from the HTTP response from OAuth. Okta is sending groups the user is a member of (it can be all or some of the groups depending on your Okta config). The method then uses that group name to add to a NetBox group. So the two group names must be exactly the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment