diff --git a/docs/configuration/security.md b/docs/configuration/security.md index 775490b70..21efc0dee 100644 --- a/docs/configuration/security.md +++ b/docs/configuration/security.md @@ -1,16 +1,5 @@ # Security & Authentication Parameters -## ALLOW_TOKEN_RETRIEVAL - -Default: `False` - -!!! note - The default value of this parameter changed from `True` to `False` in NetBox v4.3.0. - -If disabled, the values of API tokens will not be displayed after each token's initial creation. A user **must** record the value of a token prior to its creation, or it will be lost. Note that this affects _all_ users, regardless of assigned permissions. - ---- - ## ALLOWED_URL_SCHEMES !!! tip "Dynamic Configuration Parameter" diff --git a/docs/integrations/rest-api.md b/docs/integrations/rest-api.md index ed3eab316..2b97f601c 100644 --- a/docs/integrations/rest-api.md +++ b/docs/integrations/rest-api.md @@ -80,7 +80,7 @@ Likewise, the site, rack, and device objects are located under the "DCIM" applic The full hierarchy of available endpoints can be viewed by navigating to the API root in a web browser. -Each model generally has two views associated with it: a list view and a detail view. The list view is used to retrieve a list of multiple objects and to create new objects. The detail view is used to retrieve, update, or delete an single existing object. All objects are referenced by their numeric primary key (`id`). +Each model generally has two views associated with it: a list view and a detail view. The list view is used to retrieve a list of multiple objects and to create new objects. The detail view is used to retrieve, update, or delete a single existing object. All objects are referenced by their numeric primary key (`id`). * `/api/dcim/devices/` - List existing devices or create a new device * `/api/dcim/devices/123/` - Retrieve, update, or delete the device with ID 123 @@ -655,6 +655,9 @@ The NetBox REST API primarily employs token-based authentication. For convenienc A token is a secret, unique identifier mapped to a NetBox user account. Each user may have one or more tokens which he or she can use for authentication when making REST API requests. To create a token, navigate to the API tokens page under your user profile. When creating a token, NetBox will automatically populate a randomly-generated token value. +!!! note "Tokens cannot be retrieved once created" + Once a token has been created, its plaintext value cannot be retrieved. For this reason, you must take care to securely record the token locally immediately upon its creation. If a token plaintext is lost, it cannot be recovered: A new token must be created. + By default, all users can create and manage their own REST API tokens under the user control panel in the UI or via the REST API. This ability can be disabled by overriding the [`DEFAULT_PERMISSIONS`](../configuration/security.md#default_permissions) configuration parameter. Additionally, a token can be set to expire at a specific time. This can be useful if an external client needs to be granted temporary access to NetBox. @@ -663,7 +666,7 @@ Additionally, a token can be set to expire at a specific time. This can be usefu Beginning with NetBox v4.5, two versions of API token are supported, denoted as v1 and v2. Users are strongly encouraged to create only v2 tokens and to discontinue the use of v1 tokens. Support for v1 tokens will be removed in a future NetBox release. -v2 API tokens offer much stronger security. The token plaintext given at creation time is hashed together with a configured [cryptographic pepper](../configuration/required-parameters.md#api_token_peppers) to generate a unique checksum. This checksum is irreversible; the token plaintext is never stored on the server and thus cannot be retrieved. +v2 API tokens offer much stronger security. The token plaintext given at creation time is hashed together with a configured [cryptographic pepper](../configuration/required-parameters.md#api_token_peppers) to generate a unique checksum. This checksum is irreversible; the token plaintext is never stored on the server and thus cannot be retrieved even with database-level access. #### Restricting Write Operations diff --git a/netbox/netbox/configuration_example.py b/netbox/netbox/configuration_example.py index 18d30d29a..c43007c1e 100644 --- a/netbox/netbox/configuration_example.py +++ b/netbox/netbox/configuration_example.py @@ -91,9 +91,6 @@ ADMINS = [ # ('John Doe', 'jdoe@example.com'), ] -# Permit the retrieval of API tokens after their creation. -ALLOW_TOKEN_RETRIEVAL = False - # Enable any desired validators for local account passwords below. For a list of included validators, please see the # Django documentation at https://docs.djangoproject.com/en/stable/topics/auth/passwords/#password-validation. AUTH_PASSWORD_VALIDATORS = [ diff --git a/netbox/netbox/configuration_testing.py b/netbox/netbox/configuration_testing.py index 6d1de2008..3e552e944 100644 --- a/netbox/netbox/configuration_testing.py +++ b/netbox/netbox/configuration_testing.py @@ -43,8 +43,6 @@ SECRET_KEY = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' DEFAULT_PERMISSIONS = {} -ALLOW_TOKEN_RETRIEVAL = True - API_TOKEN_PEPPERS = { 1: 'TEST-VALUE-DO-NOT-USE-TEST-VALUE-DO-NOT-USE-TEST-VALUE-DO-NOT-USE', } diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index d880478e3..ca7f9c3fa 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -76,7 +76,6 @@ elif hasattr(configuration, 'DATABASE') and hasattr(configuration, 'DATABASES'): # Set static config parameters ADMINS = getattr(configuration, 'ADMINS', []) -ALLOW_TOKEN_RETRIEVAL = getattr(configuration, 'ALLOW_TOKEN_RETRIEVAL', False) ALLOWED_HOSTS = getattr(configuration, 'ALLOWED_HOSTS') # Required API_TOKEN_PEPPERS = getattr(configuration, 'API_TOKEN_PEPPERS', {}) AUTH_PASSWORD_VALIDATORS = getattr(configuration, 'AUTH_PASSWORD_VALIDATORS', [ diff --git a/netbox/templates/users/token.html b/netbox/templates/users/token.html index b3eb80b87..86e96a6f3 100644 --- a/netbox/templates/users/token.html +++ b/netbox/templates/users/token.html @@ -20,14 +20,7 @@ {% if object.version == 1 %} {% trans "Token" %} - - {% if settings.ALLOW_TOKEN_RETRIEVAL %} - {{ object.plaintext }} - - {% else %} - {{ object.partial }} - {% endif %} - + {{ object.partial }} {% else %} diff --git a/netbox/users/forms/model_forms.py b/netbox/users/forms/model_forms.py index 54857c115..cae194331 100644 --- a/netbox/users/forms/model_forms.py +++ b/netbox/users/forms/model_forms.py @@ -1,7 +1,6 @@ import json from django import forms -from django.conf import settings from django.contrib.auth import password_validation from django.contrib.postgres.forms import SimpleArrayField from django.core.exceptions import FieldError @@ -115,7 +114,7 @@ class UserTokenForm(forms.ModelForm): label=_('Token'), help_text=_( 'Tokens must be at least 40 characters in length. Be sure to record your key prior to ' - 'submitting this form, as it may no longer be accessible once the token has been created.' + 'submitting this form, as it will no longer be accessible once the token has been created.' ), widget=forms.TextInput( attrs={'data-clipboard': 'true'} @@ -148,11 +147,8 @@ class UserTokenForm(forms.ModelForm): self.fields['version'].disabled = True self.fields['user'].disabled = True - # Omit the key field when editing an existing token if token retrieval is not permitted - if self.instance.v1 and settings.ALLOW_TOKEN_RETRIEVAL: - self.initial['token'] = self.instance.plaintext - else: - del self.fields['token'] + # Omit the key field when editing an existing Token + del self.fields['token'] # Generate an initial random key if none has been specified elif self.instance._state.adding and not self.initial.get('token'): diff --git a/netbox/users/tables.py b/netbox/users/tables.py index c5207d899..2b4bd745f 100644 --- a/netbox/users/tables.py +++ b/netbox/users/tables.py @@ -11,13 +11,7 @@ __all__ = ( 'UserTable', ) -TOKEN = """{{ record }}""" - -COPY_BUTTON = """ -{% if settings.ALLOW_TOKEN_RETRIEVAL %} - {% copy_content record.pk prefix="token_" color="success" %} -{% endif %} -""" +TOKEN = """{{ record }}""" class TokenTable(NetBoxTable): @@ -48,7 +42,6 @@ class TokenTable(NetBoxTable): ) actions = columns.ActionsColumn( actions=('edit', 'delete'), - extra_buttons=COPY_BUTTON ) class Meta(NetBoxTable.Meta):