Overview

NetBox is a DCIM and IPAM tool for modeling infrastructure and serving as a source of truth for the desired state of the network. Okta is an IAM company that offers a single sign-on product, which can act as a central point to manage user access.

As of NetBox version 3.1.0, native support for SSO authentication was added via inclusion of python-social-auth. This library supports many backends, including Okta via both OAuth2 and OpenId Connect. Until then, the only options for an external authentication provider were LDAP, an external plugin, or moving the authentication to a proxy and passing the results to netbox via HTTP headers.

This is how I set up NetBox to authenticate with Okta via native SSO integration.

Requirements

  • NetBox 3.1.7 or greater
  • An Okta account

Despite NetBox adding single sign-on support in v3.1.0, there was a bug in python-social-auth] that prevented it from working with Okta. This is now fixed upstream, and NetBox requirements.txt is updated to this new version.

If you are not yet an Okta customer, or if you don’t have administrative access to your organization’s tenant, Okta offers fully-functional free developer accounts at developer.okta.com for testing integrations with their product.

Okta

Configure a NetBox application in Okta. Here is an example minimal terraform configuration as well as steps and screenshots of the manual process using the Okta administrative web interface. Choose one.

Terraform

variable "hostname" { default = "netbox.example.com" }

resource "okta_app_oauth" "netbox" {
  label                     = "NetBox"
  type                      = "web"
  grant_types               = ["authorization_code", "client_credentials", "implicit"]
  response_types            = ["code", "token", "id_token"]
  hide_web                  = false
  login_mode                = "SPEC"
  login_uri                 = "https://${var.hostname}/oauth/login/okta-openidconnect/"
  redirect_uris             = ["https://${var.hostname}/oauth/complete/okta-openidconnect/"]
  post_logout_redirect_uris = ["http://${var.hostname}/disconnect/okta-openidconnect/"]
}

data "okta_group" "everyone" { name = "Everyone" }

resource "okta_app_group_assignment" "access" {
  app_id   = okta_app_oauth.netbox.id
  group_id = data.okta_group.everyone.id
}

output "netbox_configuration" {
  sensitive = true
  value     = <<-EOM
  REMOTE_AUTH_BACKEND                    = 'social_core.backends.okta_openidconnect.OktaOpenIdConnect'
  SOCIAL_AUTH_OKTA_OPENIDCONNECT_KEY     = '${okta_app_oauth.netbox.client_id}'
  SOCIAL_AUTH_OKTA_OPENIDCONNECT_SECRET  = '${okta_app_oauth.netbox.client_secret}'
  SOCIAL_AUTH_OKTA_OPENIDCONNECT_API_URL = 'https://${var.hostname}/oauth2/'
  EOM
}

Manual

In the Okta admin portal, create a new “App Integration”. Choose OpenID Connect as the Sign-in method, and set the application type to “Web Application”.

Create App Integration

Under General Settings, set the app name, NetBox, and optionally upload a [logo]. Set the Sign-in and Sign-out redirect URIs to https://netbox.example.com/oauth/complete/okta-openidconnect and http://netbox.example.com/disconnect/okta-openidconnect/, respectively. Save.

Create New App Settings

If you’d like to also be able to initiate user login from the Okta dashboard, also select “Implicit (hybrid)” grant type, check off the applicable options under “Application Visibility”, and set “Initiate login URI” to https://netbox.example.com/oauth/login/okta-openidconnect/.

Note the “Client ID”, “Client secret”, and “Okta domain”. These will be used in configuring NetBox. There is a handy “copy to clipboard” button to the right of each field.

collect info for entering into netbox configuration
Client Credentials and Okta Domain

collect info for entering into netbox configuration

Netbox Configuration

requirements.txt

Install the python-jose dependency, and add it to local_requirements to persist this across upgrades.

root@d-netbox-a:/opt/netbox# . venv/bin/activate
(venv) root@d-netbox-a:/opt/netbox# pip install python-jose
(venv) root@d-netbox-a:/opt/netbox# echo python-jose >> local_requirements.txt

configuration.py

In configuration.py, set the following:

REMOTE_AUTH_BACKEND = 'social_core.backends.okta_openidconnect.OktaOpenIdConnect'
SOCIAL_AUTH_OKTA_OPENIDCONNECT_KEY= 'CLIENT_ID'
SOCIAL_AUTH_OKTA_OPENIDCONNECT_SECRET= 'CLIENT_SECRET'
SOCIAL_AUTH_OKTA_OPENIDCONNECT_API_URL= 'https://OKTA_DOMAIN/oauth2/'
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.social_auth.associate_by_email",
    "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"
]
REMOTE_AUTH_HEADER = 'HTTP_REMOTE_USER'
REMOTE_AUTH_AUTO_CREATE_USER = True

Change the CLIENT_ID and CLIENT_SECRET above to the “Client ID” and “Client secret” fields from the Okta admin interface. Also change the OKTA_DOMAIN to your custom domain or the “Okta domain” listed on the Okta app page.

The pipeline documentation was very helpful in determining the what would work in my environment. Specifically in my case, since I was migrating an installation using LDAP authentication, I wanted new logins to map to existing users if the email address matched, otherwise create a new user. If you have different needs, this is a good place to look for an answer.

Test

Restart NetBox and go to the login page. Click on the okta-openidconnect link to login via SSO. You can still use the username/password fields for any local accounts.

NetBox login page

If you set it up, your Okta users can also use the Okta End-User Dashboard to log into the NetBox instance.

NetBox login on Okta Dashboard