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..b580e9611 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. Be aware that disabling this setting, after users have already setup TOTP, may prevent users from logging in. 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. Be aware that disabling this setting, after users have already setup their accounts with Security Keys, may prevent users from logging in. + 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. Be aware that changing this value, after users have already setup their accounts with the previous value, may prevent users from logging in. + 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;