diff --git a/salt/kratos/defaults.yaml b/salt/kratos/defaults.yaml index e0317ed37..3f5370dde 100644 --- a/salt/kratos/defaults.yaml +++ b/salt/kratos/defaults.yaml @@ -7,6 +7,14 @@ kratos: required_aal: highest_available selfservice: methods: + webauthn: + enabled: true + config: + passwordless: true + rp: + id: URL_BASE + origin: https://URL_BASE + display_name: Security Onion (URL_BASE) password: enabled: true config: diff --git a/salt/kratos/files/schema.json b/salt/kratos/files/schema.json index 610c250d8..647c5ce24 100644 --- a/salt/kratos/files/schema.json +++ b/salt/kratos/files/schema.json @@ -1,12 +1,12 @@ { - "$id": "securityonion.schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Person", - "type": "object", - "properties": { - "traits": { - "type": "object", - "properties": { + "$id": "securityonion.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Person", + "type": "object", + "properties": { + "traits": { + "type": "object", + "properties": { "email": { "type": "string", "format": "email", @@ -20,6 +20,9 @@ }, "totp": { "account_name": true + }, + "webauthn": { + "identifier": true } }, "verification": { diff --git a/salt/kratos/map.jinja b/salt/kratos/map.jinja index 1cdc4337b..6a2b1e0c9 100644 --- a/salt/kratos/map.jinja +++ b/salt/kratos/map.jinja @@ -6,6 +6,9 @@ {% from 'vars/globals.map.jinja' import GLOBALS %} {% import_yaml 'kratos/defaults.yaml' as KRATOSDEFAULTS %} +{% do KRATOSDEFAULTS.kratos.config.selfservice.methods.webauthn.config.rp.update({'origin': KRATOSDEFAULTS.kratos.config.selfservice.methods.webauthn.config.rp.origin | replace("URL_BASE", GLOBALS.url_base)}) %} +{% do KRATOSDEFAULTS.kratos.config.selfservice.methods.webauthn.config.rp.update({'id': KRATOSDEFAULTS.kratos.config.selfservice.methods.webauthn.config.rp.id | replace("URL_BASE", GLOBALS.url_base)}) %} +{% do KRATOSDEFAULTS.kratos.config.selfservice.methods.webauthn.config.rp.update({'display_name': KRATOSDEFAULTS.kratos.config.selfservice.methods.webauthn.config.rp.display_name | replace("URL_BASE", GLOBALS.url_base)}) %} {% do KRATOSDEFAULTS.kratos.config.selfservice.flows.settings.update({'ui_url': KRATOSDEFAULTS.kratos.config.selfservice.flows.settings.ui_url | replace("URL_BASE", GLOBALS.url_base)}) %} {% do KRATOSDEFAULTS.kratos.config.selfservice.flows.verification.update({'ui_url': KRATOSDEFAULTS.kratos.config.selfservice.flows.verification.ui_url | replace("URL_BASE", GLOBALS.url_base)}) %} {% do KRATOSDEFAULTS.kratos.config.selfservice.flows.login.update({'ui_url': KRATOSDEFAULTS.kratos.config.selfservice.flows.login.ui_url | replace("URL_BASE", GLOBALS.url_base)}) %} diff --git a/salt/kratos/soc_kratos.yaml b/salt/kratos/soc_kratos.yaml index 1eb9bef40..19487abf8 100644 --- a/salt/kratos/soc_kratos.yaml +++ b/salt/kratos/soc_kratos.yaml @@ -30,9 +30,8 @@ kratos: helpLink: kratos.html totp: enabled: - description: Set to True to enable Time-based One-Time Password (TOTP) MFA authentication. Leave as default to ensure proper security protections remain in place. + description: Set to True to enable Time-based One-Time Password (TOTP) multi-factor authentication (MFA). Enable to ensure proper security protections remain in place. global: True - advanced: True helpLink: kratos.html config: issuer: @@ -40,6 +39,32 @@ kratos: global: True advanced: True helpLink: kratos.html + webauthn: + enabled: + description: Set to True to enable Security Keys (WebAuthn / PassKeys) for passwordless or multi-factor authentication (MFA) logins. Security Keys are a Public-Key Infrastructure (PKI) based authentication method, typically involving biometric hardware devices, such as laptop fingerprint scanners and USB hardware keys. + global: True + helpLink: kratos.html + config: + passwordless: + description: Set to True to utilize Security Keys (WebAuthn / PassKeys) for passwordless logins. Set to false to utilize Security Keys as a multi-factor authentication (MFA) method supplementing password logins. + global: True + helpLink: kratos.html + rp: + id: + description: The internal identification used for registering new Security Keys. Leave as default to ensure Security Keys function properly. + global: True + advanced: True + helpLink: kratos.html + origin: + description: The URL used to login to SOC. Leave as default to ensure Security Keys function properly. + global: True + advanced: True + helpLink: kratos.html + display_name: + description: The name assigned to the security key. Note that URL_BASE is replaced with the hostname or IP address used to login to SOC, to help distinguish multiple Security Onion installations. + global: True + advanced: True + helpLink: kratos.html flows: settings: privileged_session_max_age: diff --git a/salt/manager/tools/sbin/so-user b/salt/manager/tools/sbin/so-user index 8234f7ae5..50836e94c 100755 --- a/salt/manager/tools/sbin/so-user +++ b/salt/manager/tools/sbin/so-user @@ -235,8 +235,8 @@ function updatePassword() { # Update DB with new hash echo "update identity_credentials set config=CAST('{\"hashed_password\":\"$passwordHash\"}' as BLOB), created_at=datetime('now'), updated_at=datetime('now') where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name='password');" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" # Deactivate MFA - echo "delete from identity_credential_identifiers where identity_credential_id=(select id from identity_credentials where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name='totp'));" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" - echo "delete from identity_credentials where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name='totp');" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" + echo "delete from identity_credential_identifiers where identity_credential_id=(select id from identity_credentials where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name in ('totp', 'webauthn')));" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" + echo "delete from identity_credentials where identity_id='${identityId}' and identity_credential_type_id=(select id from identity_credential_types where name in ('totp', 'webauthn'));" | sqlite3 -cmd ".timeout ${databaseTimeout}" "$databasePath" [[ $? != 0 ]] && fail "Unable to update password" fi } diff --git a/salt/nginx/defaults.yaml b/salt/nginx/defaults.yaml index c82d6b5df..3c520888a 100644 --- a/salt/nginx/defaults.yaml +++ b/salt/nginx/defaults.yaml @@ -2,5 +2,5 @@ nginx: enabled: False config: replace_cert: False - throttle_login_burst: 6 - throttle_login_rate: 10 + throttle_login_burst: 12 + throttle_login_rate: 20 diff --git a/salt/nginx/etc/nginx.conf b/salt/nginx/etc/nginx.conf index 4aeb894dd..456beb451 100644 --- a/salt/nginx/etc/nginx.conf +++ b/salt/nginx/etc/nginx.conf @@ -160,7 +160,7 @@ http { proxy_set_header X-Forwarded-Proto $scheme; } - location ~ ^/auth/.*?(whoami|logout|settings) { + location ~ ^/auth/.*?(whoami|logout|settings|webauthn.js) { rewrite /auth/(.*) /$1 break; proxy_pass http://{{ GLOBALS.manager }}:4433; proxy_read_timeout 90;