feat(commands): add webauthn device commands (#3671)
parent
52102eea8c
commit
24e41aed84
|
@ -62,4 +62,5 @@ authelia storage user --help
|
||||||
* [authelia storage](authelia_storage.md) - Manage the Authelia storage
|
* [authelia storage](authelia_storage.md) - Manage the Authelia storage
|
||||||
* [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers
|
* [authelia storage user identifiers](authelia_storage_user_identifiers.md) - Manage user opaque identifiers
|
||||||
* [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations
|
* [authelia storage user totp](authelia_storage_user_totp.md) - Manage TOTP configurations
|
||||||
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
---
|
||||||
|
title: "authelia storage user webauthn"
|
||||||
|
description: "Reference for the authelia storage user webauthn command."
|
||||||
|
lead: ""
|
||||||
|
date: 2022-06-15T17:51:47+10:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
reference:
|
||||||
|
parent: "cli-authelia"
|
||||||
|
weight: 330
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## authelia storage user webauthn
|
||||||
|
|
||||||
|
Manage Webauthn devices
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Manage Webauthn devices.
|
||||||
|
|
||||||
|
This subcommand allows interacting with Webauthn devices.
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
authelia storage user webauthn --help
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for webauthn
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config strings configuration files to load (default [configuration.yml])
|
||||||
|
--encryption-key string the storage encryption key to use
|
||||||
|
--mysql.database string the MySQL database name (default "authelia")
|
||||||
|
--mysql.host string the MySQL hostname
|
||||||
|
--mysql.password string the MySQL password
|
||||||
|
--mysql.port int the MySQL port (default 3306)
|
||||||
|
--mysql.username string the MySQL username (default "authelia")
|
||||||
|
--postgres.database string the PostgreSQL database name (default "authelia")
|
||||||
|
--postgres.host string the PostgreSQL hostname
|
||||||
|
--postgres.password string the PostgreSQL password
|
||||||
|
--postgres.port int the PostgreSQL port (default 5432)
|
||||||
|
--postgres.schema string the PostgreSQL schema name (default "public")
|
||||||
|
--postgres.ssl.certificate string the PostgreSQL ssl certificate file location
|
||||||
|
--postgres.ssl.key string the PostgreSQL ssl key file location
|
||||||
|
--postgres.ssl.mode string the PostgreSQL ssl mode (default "disable")
|
||||||
|
--postgres.ssl.root_certificate string the PostgreSQL ssl root certificate file location
|
||||||
|
--postgres.username string the PostgreSQL username (default "authelia")
|
||||||
|
--sqlite.path string the SQLite database path
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [authelia storage user](authelia_storage_user.md) - Manages user settings
|
||||||
|
* [authelia storage user webauthn delete](authelia_storage_user_webauthn_delete.md) - Delete a WebAuthn device
|
||||||
|
* [authelia storage user webauthn list](authelia_storage_user_webauthn_list.md) - List WebAuthn devices
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
---
|
||||||
|
title: "authelia storage user webauthn delete"
|
||||||
|
description: "Reference for the authelia storage user webauthn delete command."
|
||||||
|
lead: ""
|
||||||
|
date: 2022-06-15T17:51:47+10:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
reference:
|
||||||
|
parent: "cli-authelia"
|
||||||
|
weight: 330
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## authelia storage user webauthn delete
|
||||||
|
|
||||||
|
Delete a WebAuthn device
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
Delete a WebAuthn device.
|
||||||
|
|
||||||
|
This subcommand allows deleting a WebAuthn device directly from the database.
|
||||||
|
|
||||||
|
```
|
||||||
|
authelia storage user webauthn delete [username] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
authelia storage user webauthn delete john --all
|
||||||
|
authelia storage user webauthn delete john --all --config config.yml
|
||||||
|
authelia storage user webauthn delete john --all --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
authelia storage user webauthn delete john --description Primary
|
||||||
|
authelia storage user webauthn delete john --description Primary --config config.yml
|
||||||
|
authelia storage user webauthn delete john --description Primary --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
authelia storage user webauthn delete --kid abc123
|
||||||
|
authelia storage user webauthn delete --kid abc123 --config config.yml
|
||||||
|
authelia storage user webauthn delete --kid abc123 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
--all delete all of the users webauthn devices
|
||||||
|
--description string delete a users webauthn device by description
|
||||||
|
-h, --help help for delete
|
||||||
|
--kid string delete a users webauthn device by key id
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config strings configuration files to load (default [configuration.yml])
|
||||||
|
--encryption-key string the storage encryption key to use
|
||||||
|
--mysql.database string the MySQL database name (default "authelia")
|
||||||
|
--mysql.host string the MySQL hostname
|
||||||
|
--mysql.password string the MySQL password
|
||||||
|
--mysql.port int the MySQL port (default 3306)
|
||||||
|
--mysql.username string the MySQL username (default "authelia")
|
||||||
|
--postgres.database string the PostgreSQL database name (default "authelia")
|
||||||
|
--postgres.host string the PostgreSQL hostname
|
||||||
|
--postgres.password string the PostgreSQL password
|
||||||
|
--postgres.port int the PostgreSQL port (default 5432)
|
||||||
|
--postgres.schema string the PostgreSQL schema name (default "public")
|
||||||
|
--postgres.ssl.certificate string the PostgreSQL ssl certificate file location
|
||||||
|
--postgres.ssl.key string the PostgreSQL ssl key file location
|
||||||
|
--postgres.ssl.mode string the PostgreSQL ssl mode (default "disable")
|
||||||
|
--postgres.ssl.root_certificate string the PostgreSQL ssl root certificate file location
|
||||||
|
--postgres.username string the PostgreSQL username (default "authelia")
|
||||||
|
--sqlite.path string the SQLite database path
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
---
|
||||||
|
title: "authelia storage user webauthn list"
|
||||||
|
description: "Reference for the authelia storage user webauthn list command."
|
||||||
|
lead: ""
|
||||||
|
date: 2022-06-15T17:51:47+10:00
|
||||||
|
draft: false
|
||||||
|
images: []
|
||||||
|
menu:
|
||||||
|
reference:
|
||||||
|
parent: "cli-authelia"
|
||||||
|
weight: 330
|
||||||
|
toc: true
|
||||||
|
---
|
||||||
|
|
||||||
|
## authelia storage user webauthn list
|
||||||
|
|
||||||
|
List WebAuthn devices
|
||||||
|
|
||||||
|
### Synopsis
|
||||||
|
|
||||||
|
List WebAuthn devices.
|
||||||
|
|
||||||
|
This subcommand allows listing WebAuthn devices.
|
||||||
|
|
||||||
|
```
|
||||||
|
authelia storage user webauthn list [username] [flags]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
authelia storage user webauthn list
|
||||||
|
authelia storage user webauthn list john
|
||||||
|
authelia storage user webauthn list --config config.yml
|
||||||
|
authelia storage user webauthn list john --config config.yml
|
||||||
|
authelia storage user webauthn list --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
|
```
|
||||||
|
-h, --help help for list
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options inherited from parent commands
|
||||||
|
|
||||||
|
```
|
||||||
|
-c, --config strings configuration files to load (default [configuration.yml])
|
||||||
|
--encryption-key string the storage encryption key to use
|
||||||
|
--mysql.database string the MySQL database name (default "authelia")
|
||||||
|
--mysql.host string the MySQL hostname
|
||||||
|
--mysql.password string the MySQL password
|
||||||
|
--mysql.port int the MySQL port (default 3306)
|
||||||
|
--mysql.username string the MySQL username (default "authelia")
|
||||||
|
--postgres.database string the PostgreSQL database name (default "authelia")
|
||||||
|
--postgres.host string the PostgreSQL hostname
|
||||||
|
--postgres.password string the PostgreSQL password
|
||||||
|
--postgres.port int the PostgreSQL port (default 5432)
|
||||||
|
--postgres.schema string the PostgreSQL schema name (default "public")
|
||||||
|
--postgres.ssl.certificate string the PostgreSQL ssl certificate file location
|
||||||
|
--postgres.ssl.key string the PostgreSQL ssl key file location
|
||||||
|
--postgres.ssl.mode string the PostgreSQL ssl mode (default "disable")
|
||||||
|
--postgres.ssl.root_certificate string the PostgreSQL ssl root certificate file location
|
||||||
|
--postgres.username string the PostgreSQL username (default "authelia")
|
||||||
|
--sqlite.path string the SQLite database path
|
||||||
|
```
|
||||||
|
|
||||||
|
### SEE ALSO
|
||||||
|
|
||||||
|
* [authelia storage user webauthn](authelia_storage_user_webauthn.md) - Manage Webauthn devices
|
||||||
|
|
|
@ -176,6 +176,43 @@ This subcommand allows manually adding an opaque identifier for a user to the da
|
||||||
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --config config.yml
|
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --config config.yml
|
||||||
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
authelia storage user identifiers add john --identifier f0919359-9d15-4e15-bcba-83b41620a073 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnShort = "Manage Webauthn devices"
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnLong = `Manage Webauthn devices.
|
||||||
|
|
||||||
|
This subcommand allows interacting with Webauthn devices.`
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnExample = `authelia storage user webauthn --help`
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnListShort = "List WebAuthn devices"
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnListLong = `List WebAuthn devices.
|
||||||
|
|
||||||
|
This subcommand allows listing WebAuthn devices.`
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnListExample = `authelia storage user webauthn list
|
||||||
|
authelia storage user webauthn list john
|
||||||
|
authelia storage user webauthn list --config config.yml
|
||||||
|
authelia storage user webauthn list john --config config.yml
|
||||||
|
authelia storage user webauthn list --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
authelia storage user webauthn list john --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnDeleteShort = "Delete a WebAuthn device"
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnDeleteLong = `Delete a WebAuthn device.
|
||||||
|
|
||||||
|
This subcommand allows deleting a WebAuthn device directly from the database.`
|
||||||
|
|
||||||
|
cmdAutheliaStorageUserWebAuthnDeleteExample = `authelia storage user webauthn delete john --all
|
||||||
|
authelia storage user webauthn delete john --all --config config.yml
|
||||||
|
authelia storage user webauthn delete john --all --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
authelia storage user webauthn delete john --description Primary
|
||||||
|
authelia storage user webauthn delete john --description Primary --config config.yml
|
||||||
|
authelia storage user webauthn delete john --description Primary --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw
|
||||||
|
authelia storage user webauthn delete --kid abc123
|
||||||
|
authelia storage user webauthn delete --kid abc123 --config config.yml
|
||||||
|
authelia storage user webauthn delete --kid abc123 --encryption-key b3453fde-ecc2-4a1f-9422-2707ddbed495 --postgres.host postgres --postgres.password autheliapw`
|
||||||
|
|
||||||
cmdAutheliaStorageUserTOTPShort = "Manage TOTP configurations"
|
cmdAutheliaStorageUserTOTPShort = "Manage TOTP configurations"
|
||||||
|
|
||||||
cmdAutheliaStorageUserTOTPLong = `Manage TOTP configurations.
|
cmdAutheliaStorageUserTOTPLong = `Manage TOTP configurations.
|
||||||
|
|
|
@ -117,6 +117,7 @@ func newStorageUserCmd() (cmd *cobra.Command) {
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
newStorageUserIdentifiersCmd(),
|
newStorageUserIdentifiersCmd(),
|
||||||
newStorageUserTOTPCmd(),
|
newStorageUserTOTPCmd(),
|
||||||
|
newStorageUserWebAuthnCmd(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
|
@ -211,6 +212,58 @@ func newStorageUserIdentifiersAddCmd() (cmd *cobra.Command) {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newStorageUserWebAuthnCmd() (cmd *cobra.Command) {
|
||||||
|
cmd = &cobra.Command{
|
||||||
|
Use: "webauthn",
|
||||||
|
Short: cmdAutheliaStorageUserWebAuthnShort,
|
||||||
|
Long: cmdAutheliaStorageUserWebAuthnLong,
|
||||||
|
Example: cmdAutheliaStorageUserWebAuthnExample,
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(
|
||||||
|
newStorageUserWebAuthnListCmd(),
|
||||||
|
newStorageUserWebAuthnDeleteCmd(),
|
||||||
|
)
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStorageUserWebAuthnListCmd() (cmd *cobra.Command) {
|
||||||
|
cmd = &cobra.Command{
|
||||||
|
Use: "list [username]",
|
||||||
|
Short: cmdAutheliaStorageUserWebAuthnListShort,
|
||||||
|
Long: cmdAutheliaStorageUserWebAuthnListLong,
|
||||||
|
Example: cmdAutheliaStorageUserWebAuthnListExample,
|
||||||
|
RunE: storageWebAuthnListRunE,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStorageUserWebAuthnDeleteCmd() (cmd *cobra.Command) {
|
||||||
|
cmd = &cobra.Command{
|
||||||
|
Use: "delete [username]",
|
||||||
|
Short: cmdAutheliaStorageUserWebAuthnDeleteShort,
|
||||||
|
Long: cmdAutheliaStorageUserWebAuthnDeleteLong,
|
||||||
|
Example: cmdAutheliaStorageUserWebAuthnDeleteExample,
|
||||||
|
RunE: storageWebAuthnDeleteRunE,
|
||||||
|
Args: cobra.MaximumNArgs(1),
|
||||||
|
|
||||||
|
DisableAutoGenTag: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().Bool("all", false, "delete all of the users webauthn devices")
|
||||||
|
cmd.Flags().String("description", "", "delete a users webauthn device by description")
|
||||||
|
cmd.Flags().String("kid", "", "delete a users webauthn device by key id")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func newStorageUserTOTPCmd() (cmd *cobra.Command) {
|
func newStorageUserTOTPCmd() (cmd *cobra.Command) {
|
||||||
cmd = &cobra.Command{
|
cmd = &cobra.Command{
|
||||||
Use: "totp",
|
Use: "totp",
|
||||||
|
|
|
@ -205,6 +205,187 @@ func storageSchemaEncryptionChangeKeyRunE(cmd *cobra.Command, args []string) (er
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func storageWebAuthnListRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
if len(args) == 0 || args[0] == "" {
|
||||||
|
return storageWebAuthnListAllRunE(cmd, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
provider storage.Provider
|
||||||
|
ctx = context.Background()
|
||||||
|
)
|
||||||
|
|
||||||
|
provider = getStorageProvider()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = provider.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
var devices []model.WebauthnDevice
|
||||||
|
|
||||||
|
user := args[0]
|
||||||
|
|
||||||
|
devices, err = provider.LoadWebauthnDevicesByUsername(ctx, user)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(devices) == 0 || (err != nil && errors.Is(err, storage.ErrNoWebauthnDevice)):
|
||||||
|
return fmt.Errorf("user '%s' has no webauthn devices", user)
|
||||||
|
case err != nil:
|
||||||
|
return fmt.Errorf("can't list devices for user '%s': %w", user, err)
|
||||||
|
default:
|
||||||
|
fmt.Printf("Webauthn Devices for user '%s':\n\n", user)
|
||||||
|
fmt.Printf("ID\tKID\tDescription\n")
|
||||||
|
|
||||||
|
for _, device := range devices {
|
||||||
|
fmt.Printf("%d\t%s\t%s", device.ID, device.KID, device.Description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storageWebAuthnListAllRunE(_ *cobra.Command, _ []string) (err error) {
|
||||||
|
var (
|
||||||
|
provider storage.Provider
|
||||||
|
ctx = context.Background()
|
||||||
|
)
|
||||||
|
|
||||||
|
provider = getStorageProvider()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = provider.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
var devices []model.WebauthnDevice
|
||||||
|
|
||||||
|
limit := 10
|
||||||
|
|
||||||
|
output := strings.Builder{}
|
||||||
|
|
||||||
|
for page := 0; true; page++ {
|
||||||
|
if devices, err = provider.LoadWebauthnDevices(ctx, limit, page); err != nil {
|
||||||
|
return fmt.Errorf("failed to list devices: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if page == 0 && len(devices) == 0 {
|
||||||
|
return errors.New("no webauthn devices in database")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, device := range devices {
|
||||||
|
output.WriteString(fmt.Sprintf("%d\t%s\t%s\t%s\n", device.ID, device.KID, device.Description, device.Username))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(devices) < limit {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Webauthn Devices:\n\nID\tKID\tDescription\tUsername\n")
|
||||||
|
fmt.Println(output.String())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storageWebAuthnDeleteRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
|
var (
|
||||||
|
provider storage.Provider
|
||||||
|
ctx = context.Background()
|
||||||
|
)
|
||||||
|
|
||||||
|
provider = getStorageProvider()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = provider.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
var (
|
||||||
|
all, byKID bool
|
||||||
|
description, kid, user string
|
||||||
|
)
|
||||||
|
|
||||||
|
if all, byKID, description, kid, user, err = storageWebAuthnDeleteGetAndValidateConfig(cmd, args); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if byKID {
|
||||||
|
if err = provider.DeleteWebauthnDevice(ctx, kid); err != nil {
|
||||||
|
return fmt.Errorf("failed to delete WebAuthn device with kid '%s': %w", kid, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Deleted WebAuthn device with kid '%s'", kid)
|
||||||
|
} else {
|
||||||
|
err = provider.DeleteWebauthnDeviceByUsername(ctx, user, description)
|
||||||
|
|
||||||
|
if all {
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete all WebAuthn devices with username '%s': %w", user, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Deleted all WebAuthn devices for user '%s'", user)
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete WebAuthn device with username '%s' and description '%s': %w", user, description, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Deleted WebAuthn device with username '%s' and description '%s'", user, description)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func storageWebAuthnDeleteGetAndValidateConfig(cmd *cobra.Command, args []string) (all, byKID bool, description, kid, user string, err error) {
|
||||||
|
if len(args) != 0 {
|
||||||
|
user = args[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
flags := 0
|
||||||
|
|
||||||
|
if cmd.Flags().Changed("all") {
|
||||||
|
if all, err = cmd.Flags().GetBool("all"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flags++
|
||||||
|
}
|
||||||
|
|
||||||
|
if cmd.Flags().Changed("description") {
|
||||||
|
if description, err = cmd.Flags().GetString("description"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flags++
|
||||||
|
}
|
||||||
|
|
||||||
|
if byKID = cmd.Flags().Changed("kid"); byKID {
|
||||||
|
if kid, err = cmd.Flags().GetString("kid"); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
flags++
|
||||||
|
}
|
||||||
|
|
||||||
|
if flags > 1 {
|
||||||
|
err = fmt.Errorf("must only supply one of the flags --all, --description, and --kid but %d were specified", flags)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if flags == 0 {
|
||||||
|
err = fmt.Errorf("must supply one of the flags --all, --description, or --kid")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if !byKID && len(user) == 0 {
|
||||||
|
err = fmt.Errorf("must supply the username or the --kid flag")
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func storageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) {
|
func storageTOTPGenerateRunE(cmd *cobra.Command, args []string) (err error) {
|
||||||
var (
|
var (
|
||||||
provider storage.Provider
|
provider storage.Provider
|
||||||
|
|
|
@ -166,6 +166,34 @@ func (mr *MockStorageMockRecorder) DeleteTOTPConfiguration(arg0, arg1 interface{
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTOTPConfiguration", reflect.TypeOf((*MockStorage)(nil).DeleteTOTPConfiguration), arg0, arg1)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTOTPConfiguration", reflect.TypeOf((*MockStorage)(nil).DeleteTOTPConfiguration), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteWebauthnDevice mocks base method.
|
||||||
|
func (m *MockStorage) DeleteWebauthnDevice(arg0 context.Context, arg1 string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "DeleteWebauthnDevice", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebauthnDevice indicates an expected call of DeleteWebauthnDevice.
|
||||||
|
func (mr *MockStorageMockRecorder) DeleteWebauthnDevice(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDevice", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDevice), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebauthnDeviceByUsername mocks base method.
|
||||||
|
func (m *MockStorage) DeleteWebauthnDeviceByUsername(arg0 context.Context, arg1, arg2 string) error {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "DeleteWebauthnDeviceByUsername", arg0, arg1, arg2)
|
||||||
|
ret0, _ := ret[0].(error)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebauthnDeviceByUsername indicates an expected call of DeleteWebauthnDeviceByUsername.
|
||||||
|
func (mr *MockStorageMockRecorder) DeleteWebauthnDeviceByUsername(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteWebauthnDeviceByUsername", reflect.TypeOf((*MockStorage)(nil).DeleteWebauthnDeviceByUsername), arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
// FindIdentityVerification mocks base method.
|
// FindIdentityVerification mocks base method.
|
||||||
func (m *MockStorage) FindIdentityVerification(arg0 context.Context, arg1 string) (bool, error) {
|
func (m *MockStorage) FindIdentityVerification(arg0 context.Context, arg1 string) (bool, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
|
|
|
@ -39,6 +39,8 @@ type Provider interface {
|
||||||
|
|
||||||
SaveWebauthnDevice(ctx context.Context, device model.WebauthnDevice) (err error)
|
SaveWebauthnDevice(ctx context.Context, device model.WebauthnDevice) (err error)
|
||||||
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt *time.Time, signCount uint32, cloneWarning bool) (err error)
|
UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rpid string, lastUsedAt *time.Time, signCount uint32, cloneWarning bool) (err error)
|
||||||
|
DeleteWebauthnDevice(ctx context.Context, kid string) (err error)
|
||||||
|
DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error)
|
||||||
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error)
|
LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error)
|
||||||
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error)
|
LoadWebauthnDevicesByUsername(ctx context.Context, username string) (devices []model.WebauthnDevice, err error)
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,10 @@ func NewSQLProvider(config *schema.Configuration, name, driverName, dataSourceNa
|
||||||
sqlUpdateWebauthnDeviceRecordSignIn: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignIn, tableWebauthnDevices),
|
sqlUpdateWebauthnDeviceRecordSignIn: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignIn, tableWebauthnDevices),
|
||||||
sqlUpdateWebauthnDeviceRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignInByUsername, tableWebauthnDevices),
|
sqlUpdateWebauthnDeviceRecordSignInByUsername: fmt.Sprintf(queryFmtUpdateWebauthnDeviceRecordSignInByUsername, tableWebauthnDevices),
|
||||||
|
|
||||||
|
sqlDeleteWebauthnDevice: fmt.Sprintf(queryFmtDeleteWebauthnDevice, tableWebauthnDevices),
|
||||||
|
sqlDeleteWebauthnDeviceByUsername: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsername, tableWebauthnDevices),
|
||||||
|
sqlDeleteWebauthnDeviceByUsernameAndDescription: fmt.Sprintf(queryFmtDeleteWebauthnDeviceByUsernameAndDescription, tableWebauthnDevices),
|
||||||
|
|
||||||
sqlUpsertDuoDevice: fmt.Sprintf(queryFmtUpsertDuoDevice, tableDuoDevices),
|
sqlUpsertDuoDevice: fmt.Sprintf(queryFmtUpsertDuoDevice, tableDuoDevices),
|
||||||
sqlDeleteDuoDevice: fmt.Sprintf(queryFmtDeleteDuoDevice, tableDuoDevices),
|
sqlDeleteDuoDevice: fmt.Sprintf(queryFmtDeleteDuoDevice, tableDuoDevices),
|
||||||
sqlSelectDuoDevice: fmt.Sprintf(queryFmtSelectDuoDevice, tableDuoDevices),
|
sqlSelectDuoDevice: fmt.Sprintf(queryFmtSelectDuoDevice, tableDuoDevices),
|
||||||
|
@ -169,6 +173,10 @@ type SQLProvider struct {
|
||||||
sqlUpdateWebauthnDeviceRecordSignIn string
|
sqlUpdateWebauthnDeviceRecordSignIn string
|
||||||
sqlUpdateWebauthnDeviceRecordSignInByUsername string
|
sqlUpdateWebauthnDeviceRecordSignInByUsername string
|
||||||
|
|
||||||
|
sqlDeleteWebauthnDevice string
|
||||||
|
sqlDeleteWebauthnDeviceByUsername string
|
||||||
|
sqlDeleteWebauthnDeviceByUsernameAndDescription string
|
||||||
|
|
||||||
// Table: duo_devices.
|
// Table: duo_devices.
|
||||||
sqlUpsertDuoDevice string
|
sqlUpsertDuoDevice string
|
||||||
sqlDeleteDuoDevice string
|
sqlDeleteDuoDevice string
|
||||||
|
@ -841,6 +849,34 @@ func (p *SQLProvider) UpdateWebauthnDeviceSignIn(ctx context.Context, id int, rp
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteWebauthnDevice deletes a registered Webauthn device.
|
||||||
|
func (p *SQLProvider) DeleteWebauthnDevice(ctx context.Context, kid string) (err error) {
|
||||||
|
if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDevice, kid); err != nil {
|
||||||
|
return fmt.Errorf("error deleting webauthn device with kid '%s': %w", kid, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteWebauthnDeviceByUsername deletes registered Webauthn devices by username or username and description.
|
||||||
|
func (p *SQLProvider) DeleteWebauthnDeviceByUsername(ctx context.Context, username, description string) (err error) {
|
||||||
|
if len(username) == 0 {
|
||||||
|
return fmt.Errorf("error deleting webauthn device with username '%s' and description '%s': username must not be empty", username, description)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(description) == 0 {
|
||||||
|
if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDeviceByUsername, username); err != nil {
|
||||||
|
return fmt.Errorf("error deleting webauthn devices for username '%s': %w", username, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, err = p.db.ExecContext(ctx, p.sqlDeleteWebauthnDeviceByUsernameAndDescription, username, description); err != nil {
|
||||||
|
return fmt.Errorf("error deleting webauthn device with username '%s' and description '%s': %w", username, description, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// LoadWebauthnDevices loads Webauthn device registrations.
|
// LoadWebauthnDevices loads Webauthn device registrations.
|
||||||
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error) {
|
func (p *SQLProvider) LoadWebauthnDevices(ctx context.Context, limit, page int) (devices []model.WebauthnDevice, err error) {
|
||||||
devices = make([]model.WebauthnDevice, 0, limit)
|
devices = make([]model.WebauthnDevice, 0, limit)
|
||||||
|
|
|
@ -61,6 +61,9 @@ func NewPostgreSQLProvider(config *schema.Configuration) (provider *PostgreSQLPr
|
||||||
provider.sqlUpdateWebauthnDevicePublicKeyByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDevicePublicKeyByUsername)
|
provider.sqlUpdateWebauthnDevicePublicKeyByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDevicePublicKeyByUsername)
|
||||||
provider.sqlUpdateWebauthnDeviceRecordSignIn = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignIn)
|
provider.sqlUpdateWebauthnDeviceRecordSignIn = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignIn)
|
||||||
provider.sqlUpdateWebauthnDeviceRecordSignInByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignInByUsername)
|
provider.sqlUpdateWebauthnDeviceRecordSignInByUsername = provider.db.Rebind(provider.sqlUpdateWebauthnDeviceRecordSignInByUsername)
|
||||||
|
provider.sqlDeleteWebauthnDevice = provider.db.Rebind(provider.sqlDeleteWebauthnDevice)
|
||||||
|
provider.sqlDeleteWebauthnDeviceByUsername = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsername)
|
||||||
|
provider.sqlDeleteWebauthnDeviceByUsernameAndDescription = provider.db.Rebind(provider.sqlDeleteWebauthnDeviceByUsernameAndDescription)
|
||||||
|
|
||||||
provider.sqlSelectDuoDevice = provider.db.Rebind(provider.sqlSelectDuoDevice)
|
provider.sqlSelectDuoDevice = provider.db.Rebind(provider.sqlSelectDuoDevice)
|
||||||
provider.sqlDeleteDuoDevice = provider.db.Rebind(provider.sqlDeleteDuoDevice)
|
provider.sqlDeleteDuoDevice = provider.db.Rebind(provider.sqlDeleteDuoDevice)
|
||||||
|
|
|
@ -165,6 +165,18 @@ const (
|
||||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||||
ON CONFLICT (username, description)
|
ON CONFLICT (username, description)
|
||||||
DO UPDATE SET created_at = $1, last_used_at = $2, rpid = $3, kid = $6, public_key = $7, attestation_type = $8, transport = $9, aaguid = $10, sign_count = $11, clone_warning = $12;`
|
DO UPDATE SET created_at = $1, last_used_at = $2, rpid = $3, kid = $6, public_key = $7, attestation_type = $8, transport = $9, aaguid = $10, sign_count = $11, clone_warning = $12;`
|
||||||
|
|
||||||
|
queryFmtDeleteWebauthnDevice = `
|
||||||
|
DELETE FROM %s
|
||||||
|
WHERE kid = ?;`
|
||||||
|
|
||||||
|
queryFmtDeleteWebauthnDeviceByUsername = `
|
||||||
|
DELETE FROM %s
|
||||||
|
WHERE username = ?;`
|
||||||
|
|
||||||
|
queryFmtDeleteWebauthnDeviceByUsernameAndDescription = `
|
||||||
|
DELETE FROM %s
|
||||||
|
WHERE username = ? AND description = ?;`
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
Loading…
Reference in New Issue