Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cert auth #223

Merged
merged 40 commits into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
06f9965
Initial implementation of certificate rest api authentication
dboulware Jul 29, 2022
5664774
Use env variable to set admin user name.
dboulware Jul 29, 2022
c0e2574
Add ADMIN_NAME setting to be able to pass CN of admin user do db crea…
dboulware Jan 20, 2023
04c1f55
raise exception if user not found, remove token auth and session auth
jhazentia Jan 23, 2023
adbdd0b
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Jan 23, 2023
16b3f05
cert auth in migration and runtime settings
jhazentia Jan 23, 2023
9cb4c80
update requirements
jhazentia Jan 23, 2023
ba037ab
remove pyjwt from requirements
jhazentia Jan 23, 2023
a7d5291
update readme
jhazentia Jan 23, 2023
8b9d253
remove jwt/oauth, change permission to IsSuperuser
jhazentia Jan 24, 2023
dfc673d
fix tests for cert auth, remove oauth variables from settings, fix sc…
jhazentia Jan 24, 2023
d36ce6b
update README, remove unused files, fix tests, cleanup, exception han…
jhazentia Jan 27, 2023
1846c2c
update openapi security definitions, autoformatting, settings comment
jhazentia Jan 27, 2023
6b21fc6
remove oauth/jwt from isort; autoformat settings, openapi.json
jhazentia Jan 27, 2023
89a3b48
remove old oauth params
jhazentia Jan 30, 2023
6d1a256
remove login url when using cert auth
jhazentia Jan 31, 2023
a5fd9de
update last_login, nginx check ssl_client_verify
jhazentia Jan 31, 2023
a423430
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Mar 29, 2023
fcbc88e
fix merge issue for requirements-dev.in
jhazentia Mar 29, 2023
bfcc86c
fix comment
jhazentia Apr 5, 2023
41bfa03
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Apr 5, 2023
7409e93
update authentication information in readme
jhazentia Apr 10, 2023
761bcdc
keep logout url for page timeout
jhazentia Apr 17, 2023
32a340c
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Sep 27, 2023
38d369f
update dependencies, fix dependabot alert
jhazentia Sep 27, 2023
a04ea35
formatting updates
jhazentia Sep 27, 2023
457e38c
Update env.template
jhazentia Oct 24, 2023
f54010b
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Nov 1, 2023
8850365
dependency updates
jhazentia Nov 1, 2023
740c89a
support multiple users in create_superuser, fix get username from cer…
jhazentia Nov 20, 2023
0f9e3b3
update min versions for dependabot alerts
jhazentia Nov 20, 2023
4de3426
set defaults for token auth
jhazentia Nov 29, 2023
7c858b5
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Dec 1, 2023
2c11834
update requirements
jhazentia Dec 1, 2023
e33d479
revert ray version
jhazentia Dec 1, 2023
e891c21
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Dec 4, 2023
3590675
address feedback, remove unneeded env variables from tox.ini
jhazentia Jan 8, 2024
e9b2f30
address more feedback
jhazentia Jan 8, 2024
f15ae64
add some additional fixes to create_supseruser.py, address feedback f…
jhazentia Jan 16, 2024
dfa62b0
Merge branch 'master' of https://github.com/NTIA/scos-sensor into cer…
jhazentia Jan 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
218 changes: 113 additions & 105 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion configs/certs/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Certs

Add SSL certs and JWT public key here.
Add SSL certs here.
7 changes: 3 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,15 @@ services:
- DEBUG
- DOCKER_GIT_CREDENTIALS
environment:
- ADMIN_NAME
- ADMIN_EMAIL
- ADMIN_PASSWORD
- ADDITIONAL_USER_NAMES
- ADDITIONAL_USER_PASSWORD
- AUTHENTICATION
- CALLBACK_AUTHENTICATION
- CALLBACK_SSL_VERIFICATION
- CALLBACK_TIMEOUT
- CLIENT_ID
- CLIENT_SECRET
- DEBUG
- DOCKER_TAG
- DOMAINS
Expand All @@ -53,9 +54,7 @@ services:
- MAX_DISK_USAGE
- MOCK_SIGAN
- MOCK_SIGAN_RANDOM
- OAUTH_TOKEN_URL
- PATH_TO_CLIENT_CERT
- PATH_TO_JWT_PUBLIC_KEY
- PATH_TO_VERIFY_CERT
- POSTGRES_PASSWORD
- SCOS_SENSOR_GIT_TAG
Expand Down
53 changes: 30 additions & 23 deletions docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
},
"host": "testserver",
"schemes": [
"http"
"https"
],
"basePath": "/api",
"consumes": [
Expand All @@ -24,14 +24,21 @@
"application/json"
],
"securityDefinitions": {
"cert": {
"type": "cert",
"description": "Certificate based mutual TLS authentication. AUTHENTICATION must be set to 'CERT'. This is done by the client verifying the server certificate and the server verifying the client certificate. The client certificate Common Name (CN) should contain the username of a user that exists in the database. Client certificate verification is handled by NGINX. For more information, see https://www.rfc-editor.org/rfc/rfc5246."
},
"token": {
"type": "apiKey",
"description": "Tokens are automatically generated for all users. You can view yours by going to your User Details view in the browsable API at `/api/v1/users/me` and looking for the `auth_token` key. New user accounts do not initially have a password and so can not log in to the browsable API. To set a password for a user (for testing purposes), an admin can do that in the Sensor Configuration Portal, but only the account's token should be stored and used for general purpose API access. Example cURL call: `curl -kLsS -H \"Authorization: Token 529c30e6e04b3b546f2e073e879b75fdfa147c15\" https://localhost/api/v1`",
"description": "Tokens are automatically generated for all users. You can view yours by going to your User Details view in the browsable API at `/api/v1/users/me` and looking for the `auth_token` key. New user accounts do not initially have a password and so can not log in to the browsable API. To set a password for a user (for testing purposes), an admin can do that in the Sensor Configuration Portal, but only the account's token should be stored and used for general purpose API access. Example cURL call: `curl -kLsS -H \"Authorization: Token 529c30e6e04b3b546f2e073e879b75fdfa147c15\" https://localhost/api/v1`. AUTHENTICATION should be set to 'TOKEN'",
"name": "Token",
"in": "header"
}
},
"security": [
{
"cert": []
},
{
"token": []
}
Expand Down Expand Up @@ -642,13 +649,13 @@
},
"parameters": [
{
"name": "format",
"name": "schedule_entry_name",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "schedule_entry_name",
"name": "format",
"in": "path",
"required": true,
"type": "string"
Expand Down Expand Up @@ -752,12 +759,6 @@
]
},
"parameters": [
{
"name": "format",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "schedule_entry_name",
"in": "path",
Expand All @@ -770,6 +771,12 @@
"description": "The id of the task relative to the result",
"required": true,
"type": "integer"
},
{
"name": "format",
"in": "path",
"required": true,
"type": "string"
}
]
},
Expand Down Expand Up @@ -804,12 +811,6 @@
]
},
"parameters": [
{
"name": "format",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "schedule_entry_name",
"in": "path",
Expand All @@ -822,6 +823,12 @@
"description": "The id of the task relative to the result",
"required": true,
"type": "integer"
},
{
"name": "format",
"in": "path",
"required": true,
"type": "string"
}
]
},
Expand Down Expand Up @@ -911,13 +918,13 @@
},
"parameters": [
{
"name": "format",
"name": "schedule_entry_name",
"in": "path",
"required": true,
"type": "string"
},
{
"name": "schedule_entry_name",
"name": "format",
"in": "path",
"required": true,
"type": "string"
Expand Down Expand Up @@ -1570,17 +1577,17 @@
},
"parameters": [
{
"name": "format",
"name": "id",
"in": "path",
"description": "A unique integer value identifying this user.",
"required": true,
"type": "string"
"type": "integer"
},
{
"name": "id",
"name": "format",
"in": "path",
"description": "A unique integer value identifying this user.",
"required": true,
"type": "integer"
"type": "string"
}
]
},
Expand Down
21 changes: 9 additions & 12 deletions env.template
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ GIT_BRANCH="git:$(git rev-parse --abbrev-ref HEAD)@$(git rev-parse --short HEAD)
# If admin user email and password set, admin user will be generated.
ADMIN_EMAIL="[email protected]"
ADMIN_PASSWORD=password
ADMIN_NAME=Admin
ADDITIONAL_USER_NAMES="" # comma separated
ADDITIONAL_USER_PASSWORD=""

# Session password for Postgres. Username is "postgres".
# SECURITY WARNING: generate unique key with something like
# `openssl rand -base64 12`
POSTGRES_PASSWORD="$(python3 -c 'import secrets; import base64; print(base64.b64encode(secrets.token_bytes(32)).decode("utf-8"))')"

# Set to enable monitoring sensors with your sentry.io account
SENTRY_DSN=

if $DEBUG; then
GUNICORN_LOG_LEVEL=debug
RAY_record_ref_creation_sites=1
Expand All @@ -64,18 +64,15 @@ MANAGER_IP="$(hostname -I | cut -d' ' -f1)"

BASE_IMAGE=ghcr.io/ntia/scos-tekrsa/tekrsa_usb:0.2.3
# Default callback api/results
# Set to OAUTH if using OAuth Password Flow Authentication, callback url needs to be api/v2/results
# Set to CERT for certificate authentication
CALLBACK_AUTHENTICATION=TOKEN
CALLBACK_TIMEOUT=2

CLIENT_ID=sensor01.sms.internal
CLIENT_SECRET=sensor-secret

# Sensor certificate with private key used as client cert
# Sensor certificate with private key used as client cert for callback URL
# Paths relative to configs/certs
PATH_TO_CLIENT_CERT=sensor01.pem
# Trusted Certificate Authority certificate to verify authserver and callback URL server certificate
# Trusted Certificate Authority certificate to verify callback URL server certificate
PATH_TO_VERIFY_CERT=scos_test_ca.crt
# Path relative to configs/certs
PATH_TO_JWT_PUBLIC_KEY=jwt_pubkey.pem
# set to JWT to enable JWT authentication

# set to CERT to enable scos-sensor certificate authentication
AUTHENTICATION=TOKEN
7 changes: 5 additions & 2 deletions nginx/conf.template
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ server {
ssl_session_tickets off;
ssl_certificate /etc/ssl/certs/ssl-cert.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert.key;
ssl_protocols TLSv1.2;
ssl_client_certificate /etc/ssl/certs/ca.crt;
ssl_protocols TLSv1.2 TLSv1.3;
# ssl_client_certificate /etc/ssl/certs/ca.crt;
# ssl_verify_client on;
# ssl_ocsp on; # Enable OCSP validation
ssl_verify_depth 4;
Expand All @@ -49,11 +49,14 @@ server {

# Pass off requests to Gunicorn
location @proxy_to_wsgi_server {

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Host $http_host;
proxy_set_header X-SSL-CLIENT-DN $ssl_client_s_dn;
proxy_redirect off;
proxy_pass http://wsgi-server;

}

}
55 changes: 46 additions & 9 deletions scripts/create_superuser.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,61 @@
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sensor.settings")
django.setup()

UserModel = get_user_model()


def add_user(username, password, email=None):
try:
admin_user = UserModel._default_manager.get(username=username)
if email:
admin_user.email = email
admin_user.set_password(password)
admin_user.save()
print("Reset admin account password and email from environment")
except UserModel.DoesNotExist:
UserModel._default_manager.create_superuser(username, email, password)
print("Created admin account with password and email from environment")


try:
password = os.environ["ADMIN_PASSWORD"]
print("Retreived admin password from environment variable ADMIN_PASSWORD")
email = os.environ["ADMIN_EMAIL"]
print("Retreived admin email from environment variable ADMIN_EMAIL")
username = os.environ["ADMIN_NAME"]
print("Retreived admin name from environment variable ADMIN_NAME")
add_user(username.strip(), password.strip(), email.strip())
except KeyError:
print("Not on a managed sensor, so not auto-generating admin account.")
print("You can add an admin later with `./manage.py createsuperuser`")
sys.exit(0)

UserModel = get_user_model()

additional_user_names = ""
additional_user_password = ""
try:
admin_user = UserModel._default_manager.get(username="admin")
admin_user.email = email
admin_user.set_password(password)
print("Reset admin account password and email from environment")
except UserModel.DoesNotExist:
UserModel._default_manager.create_superuser("admin", email, password)
print("Created admin account with password and email from environment")
additional_user_names = os.environ["ADDITIONAL_USER_NAMES"]
print(
"Retreived additional user names from environment variable ADDITIONAL_USER_NAMES"
)
if (
"ADDITIONAL_USER_PASSWORD" in os.environ
and os.environ["ADDITIONAL_USER_PASSWORD"]
):
additional_user_password = os.environ["ADDITIONAL_USER_PASSWORD"].strip()
else:
# user will have unusable password
# https://docs.djangoproject.com/en/3.2/ref/contrib/auth/#django.contrib.auth.models.UserManager.create_user
additional_user_password = None
print(
"Retreived additional user password from environment variable ADDITIONAL_USER_PASSWORD"
)
except KeyError:
print("Not creating any additonal users.")


if additional_user_names != "" and additional_user_password != "":
if "," in additional_user_names:
for additional_user_name in additional_user_names.split(","):
add_user(additional_user_name.strip(), additional_user_password)
else:
add_user(additional_user_names.strip(), additional_user_password)
66 changes: 0 additions & 66 deletions scripts/restore_fixture.sh

This file was deleted.

2 changes: 1 addition & 1 deletion src/.isort.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ include_trailing_comma=True
force_grid_wrap=0
use_parentheses=True
line_length=88
known_third_party=cryptography,django,drf_yasg,environs,its_preselector,jsonfield,jwt,numpy,oauthlib,pytest,requests,requests_mock,requests_oauthlib,rest_framework,scos_actions,sigmf
known_third_party=cryptography,django,drf_yasg,environs,its_preselector,jsonfield,numpy,pytest,requests,requests_mock,rest_framework,scos_actions,sigmf
Loading