diff --git a/.drone.jsonnet b/.drone.jsonnet index f56dc027..a3b3bbac 100644 --- a/.drone.jsonnet +++ b/.drone.jsonnet @@ -10,7 +10,7 @@ local bootstrap = '25.02'; local nginx = '1.24.0'; local python = '3.12-slim-bookworm'; local alpine = '3.21'; -local visual_diff_skip_build = '2884'; +local visual_diff_skip_build = '2914'; local build(arch, testUI) = [{ kind: 'pipeline', diff --git a/backend/auth/authelia.go b/backend/auth/authelia.go index 175a7c7b..b2af1a8d 100644 --- a/backend/auth/authelia.go +++ b/backend/auth/authelia.go @@ -125,7 +125,7 @@ func NewAuthelia( func (w *Authelia) RegisterOIDCClient( id string, - redirectURI string, + redirectURIs []string, requirePkce bool, tokenEndpointAuthMethod string, ) (string, error) { @@ -137,7 +137,7 @@ func (w *Authelia) RegisterOIDCClient( err = w.oidc.AddClient(config.OIDCClient{ ID: id, Secret: secret.Hash, - RedirectURI: redirectURI, + RedirectURIs: redirectURIs, RequirePkce: requirePkce, TokenEndpointAuthMethod: tokenEndpointAuthMethod, }) @@ -181,7 +181,10 @@ func (w *Authelia) InitConfig() error { return err } for i := range clients { - clients[i].RedirectURI = w.userConfig.Url(clients[i].ID) + clients[i].RedirectURI + appUrl := w.userConfig.Url(clients[i].ID) + for j, redirectURI := range clients[i].RedirectURIs { + clients[i].RedirectURIs[j] = appUrl + redirectURI + } } variables := Variables{ Domain: w.userConfig.GetDeviceDomain(), diff --git a/backend/auth/authelia_test.go b/backend/auth/authelia_test.go index 616b1b47..9d0b8e5d 100644 --- a/backend/auth/authelia_test.go +++ b/backend/auth/authelia_test.go @@ -136,8 +136,8 @@ type Client struct { func TestAutheliaClients(t *testing.T) { userConfig := &UserConfigStub{domain: "example.com", activated: false} oidc := &OIDCStub{clients: []config.OIDCClient{ - {ID: "app1", Secret: "app1secret", RedirectURI: "/callback1"}, - {ID: "app2", Secret: "app2secret", RedirectURI: "/callback2"}, + {ID: "app1", Secret: "app1secret", RedirectURIs: []string{"/callback1"}}, + {ID: "app2", Secret: "app2secret", RedirectURIs: []string{"/callback2", "/mobile2"}}, }} outDir := t.TempDir() secretDir := t.TempDir() @@ -162,5 +162,7 @@ func TestAutheliaClients(t *testing.T) { assert.Equal(t, "app2", gen.IdentityProviders.OIDC.Clients[2].ClientID) assert.Equal(t, "app2secret", gen.IdentityProviders.OIDC.Clients[2].ClientSecret) + assert.Len(t, gen.IdentityProviders.OIDC.Clients[2].RedirectUris, 2) assert.Equal(t, "https://app2.example.com/callback2", gen.IdentityProviders.OIDC.Clients[2].RedirectUris[0]) + assert.Equal(t, "https://app2.example.com/mobile2", gen.IdentityProviders.OIDC.Clients[2].RedirectUris[1]) } diff --git a/backend/config/migrator.go b/backend/config/migrator.go index 421f2a5d..56cd51c9 100644 --- a/backend/config/migrator.go +++ b/backend/config/migrator.go @@ -1,8 +1,11 @@ package config import ( + "context" + "database/sql" "fmt" - "os" + + "github.com/pressly/goose/v3" ) type Migrator struct { @@ -13,53 +16,119 @@ func NewMigrator(db *Db) *Migrator { return &Migrator{db: db} } -func (m *Migrator) Migrate() error { - _, err := os.Stat(m.db.File()) - if os.IsNotExist(err) { - if err := m.db.Init(); err != nil { - return err - } +func migrations() []*goose.Migration { + return []*goose.Migration{ + goose.NewGoMigration(1, &goose.GoFunc{RunTx: createConfigTable}, nil), + goose.NewGoMigration(2, &goose.GoFunc{RunTx: createOidcClientTable}, nil), + goose.NewGoMigration(3, &goose.GoFunc{RunTx: createCustomProxyTable}, nil), + goose.NewGoMigration(4, &goose.GoFunc{RunTx: addCustomProxyHttps}, nil), + goose.NewGoMigration(5, &goose.GoFunc{RunTx: addCustomProxyAuthelia}, nil), + goose.NewGoMigration(6, &goose.GoFunc{RunTx: normalizeOidcRedirectUris}, nil), } +} + +func (m *Migrator) provider() (*goose.Provider, error) { + return goose.NewProvider(goose.DialectSQLite3, m.db.Open(), nil, goose.WithGoMigrations(migrations()...)) +} - if err := m.addOidcClientTable(); err != nil { +func (m *Migrator) Migrate() error { + provider, err := m.provider() + if err != nil { return err } - if err := m.addCustomProxyTable(); err != nil { + defer provider.Close() + _, err = provider.Up(context.Background()) + return err +} + +func (m *Migrator) MigrateTo(version int64) error { + provider, err := m.provider() + if err != nil { return err } - if err := m.migrateCustomProxyHttps(); err != nil { + defer provider.Close() + _, err = provider.UpTo(context.Background(), version) + return err +} + +func createConfigTable(_ context.Context, tx *sql.Tx) error { + _, err := tx.Exec("create table if not exists config (key varchar primary key, value varchar)") + return err +} + +func createOidcClientTable(_ context.Context, tx *sql.Tx) error { + _, err := tx.Exec(`create table if not exists oidc_client + (id varchar primary key, secret varchar, redirect_uri varchar, require_pkce integer, token_endpoint_auth_method varchar)`) + return err +} + +func createCustomProxyTable(_ context.Context, tx *sql.Tx) error { + _, err := tx.Exec("create table if not exists custom_proxy (name varchar primary key, host varchar, port integer)") + return err +} + +func addCustomProxyHttps(ctx context.Context, tx *sql.Tx) error { + return addColumnIfMissing(ctx, tx, "custom_proxy", "https", "integer not null default 0") +} + +func addCustomProxyAuthelia(ctx context.Context, tx *sql.Tx) error { + return addColumnIfMissing(ctx, tx, "custom_proxy", "authelia", "integer not null default 0") +} + +func normalizeOidcRedirectUris(ctx context.Context, tx *sql.Tx) error { + _, err := tx.Exec(`create table if not exists oidc_redirect_uri + (client_id varchar not null, redirect_uri varchar not null)`) + if err != nil { return err } - if err := m.migrateCustomProxyAuthelia(); err != nil { + + hasLegacyColumn, err := columnExists(ctx, tx, "oidc_client", "redirect_uri") + if err != nil { return err } - return nil -} + if !hasLegacyColumn { + return nil + } -func (m *Migrator) addOidcClientTable() error { - _, err := m.db.Exec(`create table if not exists oidc_client - (id varchar primary key, secret varchar, redirect_uri varchar, require_pkce integer, token_endpoint_auth_method varchar)`) + _, err = tx.Exec(`insert into oidc_redirect_uri (client_id, redirect_uri) + select id, redirect_uri from oidc_client + where redirect_uri != '' and id not in (select client_id from oidc_redirect_uri)`) if err != nil { - return fmt.Errorf("unable to add oidc_clients: %s", err) + return err } - return nil + + _, err = tx.Exec("ALTER TABLE oidc_client DROP COLUMN redirect_uri") + return err } -func (m *Migrator) addCustomProxyTable() error { - _, err := m.db.Exec(`create table if not exists custom_proxy - (name varchar primary key, host varchar, port integer)`) +func addColumnIfMissing(ctx context.Context, tx *sql.Tx, table, column, definition string) error { + exists, err := columnExists(ctx, tx, table, column) if err != nil { - return fmt.Errorf("unable to add custom_proxy table: %s", err) + return err } - return nil -} - -func (m *Migrator) migrateCustomProxyHttps() error { - _, _ = m.db.Exec("ALTER TABLE custom_proxy ADD COLUMN https integer not null default 0") - return nil + if exists { + return nil + } + _, err = tx.Exec(fmt.Sprintf("ALTER TABLE %s ADD COLUMN %s %s", table, column, definition)) + return err } -func (m *Migrator) migrateCustomProxyAuthelia() error { - _, _ = m.db.Exec("ALTER TABLE custom_proxy ADD COLUMN authelia integer not null default 0") - return nil +func columnExists(ctx context.Context, tx *sql.Tx, table, column string) (bool, error) { + rows, err := tx.QueryContext(ctx, fmt.Sprintf("PRAGMA table_info(%s)", table)) + if err != nil { + return false, err + } + defer rows.Close() + for rows.Next() { + var cid, notnull, pk int + var name, columnType string + var defaultValue sql.NullString + if err := rows.Scan(&cid, &name, &columnType, ¬null, &defaultValue, &pk); err != nil { + return false, err + } + if name == column { + return true, nil + } + } + return false, rows.Err() } diff --git a/backend/config/migrator_test.go b/backend/config/migrator_test.go index 1c53ab54..f30e8ed0 100644 --- a/backend/config/migrator_test.go +++ b/backend/config/migrator_test.go @@ -18,8 +18,67 @@ func TestMigrator_CreatesSchemaFromScratch(t *testing.T) { _, err := db.Exec("INSERT INTO custom_proxy(name, host, port, https, authelia) VALUES ('p', 'h', 1, 0, 1)") assert.NoError(t, err) - _, err = db.Exec("INSERT INTO oidc_client VALUES ('id', 's', '/cb', 0, 'm')") + _, err = db.Exec("INSERT INTO oidc_client(id, secret, require_pkce, token_endpoint_auth_method) VALUES ('id', 's', 0, 'm')") assert.NoError(t, err) + _, err = db.Exec("INSERT INTO oidc_redirect_uri(client_id, redirect_uri) VALUES ('id', '/cb')") + assert.NoError(t, err) +} + +func TestMigrator_UpgradesPreGooseDbWithoutVersionTable(t *testing.T) { + dbFile := path.Join(t.TempDir(), "db") + + pre, err := sql.Open("sqlite", fmt.Sprintf("file:%s?_pragma=busy_timeout(5000)&_pragma=journal_mode(WAL)", dbFile)) + assert.NoError(t, err) + _, err = pre.Exec("create table config (key varchar primary key, value varchar)") + assert.NoError(t, err) + _, err = pre.Exec(`create table oidc_client + (id varchar primary key, secret varchar, redirect_uri varchar, require_pkce integer, token_endpoint_auth_method varchar)`) + assert.NoError(t, err) + _, err = pre.Exec("INSERT INTO oidc_client VALUES ('legacy', 's', '/old/callback', 1, 'client_secret_basic')") + assert.NoError(t, err) + _, err = pre.Exec("create table custom_proxy (name varchar primary key, host varchar, port integer, https integer not null default 0, authelia integer not null default 0)") + assert.NoError(t, err) + assert.NoError(t, pre.Close()) + + assert.NoError(t, NewMigrator(NewDb(dbFile, log.Default())).Migrate()) + + db := NewDb(dbFile, log.Default()) + clients, err := NewOIDC(db).Clients() + assert.NoError(t, err) + assert.Len(t, clients, 1) + assert.Equal(t, []string{"/old/callback"}, clients[0].RedirectURIs) + + conn := db.Open() + defer conn.Close() + _, err = conn.Query("select redirect_uri from oidc_client") + assert.Error(t, err, "legacy redirect_uri column must be dropped on a pre-goose db") +} + +func TestMigrator_MigratesLegacyRedirectUriIntoTableAndDropsColumn(t *testing.T) { + db := NewDb(path.Join(t.TempDir(), "db"), log.Default()) + m := NewMigrator(db) + + assert.NoError(t, m.MigrateTo(5)) + _, err := db.Exec("INSERT INTO oidc_client(id, secret, redirect_uri, require_pkce, token_endpoint_auth_method) VALUES ('app', 's', '/old/callback', 1, 'client_secret_basic')") + assert.NoError(t, err) + + assert.NoError(t, m.Migrate()) + + conn := db.Open() + defer conn.Close() + + rows, err := conn.Query("select client_id, redirect_uri from oidc_redirect_uri") + assert.NoError(t, err) + defer rows.Close() + assert.True(t, rows.Next()) + var clientID, redirectURI string + assert.NoError(t, rows.Scan(&clientID, &redirectURI)) + assert.Equal(t, "app", clientID) + assert.Equal(t, "/old/callback", redirectURI) + assert.False(t, rows.Next()) + + _, err = conn.Query("select redirect_uri from oidc_client") + assert.Error(t, err, "legacy redirect_uri column must be dropped from oidc_client") } func TestMigrator_IsIdempotent(t *testing.T) { diff --git a/backend/config/oidc.go b/backend/config/oidc.go index d077b2d8..c9995baa 100644 --- a/backend/config/oidc.go +++ b/backend/config/oidc.go @@ -3,7 +3,7 @@ package config type OIDCClient struct { ID string Secret string - RedirectURI string + RedirectURIs []string RequirePkce bool TokenEndpointAuthMethod string } @@ -19,7 +19,26 @@ func NewOIDC(db *Db) *OIDC { func (o *OIDC) Clients() ([]OIDCClient, error) { db := o.db.Open() defer db.Close() - rows, err := db.Query("select id, secret, redirect_uri, require_pkce, token_endpoint_auth_method from oidc_client") + + uriRows, err := db.Query("select client_id, redirect_uri from oidc_redirect_uri order by rowid") + if err != nil { + return nil, err + } + urisByClient := map[string][]string{} + for uriRows.Next() { + var clientID, redirectURI string + if err := uriRows.Scan(&clientID, &redirectURI); err != nil { + uriRows.Close() + return nil, err + } + urisByClient[clientID] = append(urisByClient[clientID], redirectURI) + } + uriRows.Close() + if err := uriRows.Err(); err != nil { + return nil, err + } + + rows, err := db.Query("select id, secret, require_pkce, token_endpoint_auth_method from oidc_client") if err != nil { return nil, err } @@ -32,13 +51,13 @@ func (o *OIDC) Clients() ([]OIDCClient, error) { if err := rows.Scan( &client.ID, &client.Secret, - &client.RedirectURI, &requirePkce, &client.TokenEndpointAuthMethod, ); err != nil { return clients, err } client.RequirePkce = requirePkce != 0 + client.RedirectURIs = urisByClient[client.ID] clients = append(clients, client) } return clients, rows.Err() @@ -49,8 +68,33 @@ func (o *OIDC) AddClient(client OIDCClient) error { if client.RequirePkce { requirePkce = 1 } - _, err := o.db.Exec("INSERT OR REPLACE INTO oidc_client VALUES (?, ?, ?, ?, ?)", - client.ID, client.Secret, client.RedirectURI, requirePkce, client.TokenEndpointAuthMethod, - ) - return err + + db := o.db.Open() + defer db.Close() + tx, err := db.Begin() + if err != nil { + return err + } + + if _, err := tx.Exec( + "INSERT OR REPLACE INTO oidc_client(id, secret, require_pkce, token_endpoint_auth_method) VALUES (?, ?, ?, ?)", + client.ID, client.Secret, requirePkce, client.TokenEndpointAuthMethod, + ); err != nil { + tx.Rollback() + return err + } + if _, err := tx.Exec("DELETE FROM oidc_redirect_uri WHERE client_id = ?", client.ID); err != nil { + tx.Rollback() + return err + } + for _, redirectURI := range client.RedirectURIs { + if _, err := tx.Exec( + "INSERT INTO oidc_redirect_uri(client_id, redirect_uri) VALUES (?, ?)", + client.ID, redirectURI, + ); err != nil { + tx.Rollback() + return err + } + } + return tx.Commit() } diff --git a/backend/config/oidc_test.go b/backend/config/oidc_test.go index 0d58e641..c44400d3 100644 --- a/backend/config/oidc_test.go +++ b/backend/config/oidc_test.go @@ -13,13 +13,13 @@ func newTestOIDC(t *testing.T) *OIDC { return NewOIDC(db) } -func TestOIDC_AddAndList_RoundTripsRawRedirectURI(t *testing.T) { +func TestOIDC_AddAndList_RoundTripsRedirectURI(t *testing.T) { o := newTestOIDC(t) err := o.AddClient(OIDCClient{ ID: "app1", Secret: "secret", - RedirectURI: "/callback", + RedirectURIs: []string{"/callback"}, RequirePkce: true, TokenEndpointAuthMethod: "client_secret_post", }) @@ -30,7 +30,7 @@ func TestOIDC_AddAndList_RoundTripsRawRedirectURI(t *testing.T) { assert.Len(t, clients, 1) assert.Equal(t, "app1", clients[0].ID) assert.Equal(t, "secret", clients[0].Secret) - assert.Equal(t, "/callback", clients[0].RedirectURI) + assert.Equal(t, []string{"/callback"}, clients[0].RedirectURIs) assert.True(t, clients[0].RequirePkce) assert.Equal(t, "client_secret_post", clients[0].TokenEndpointAuthMethod) } @@ -38,14 +38,14 @@ func TestOIDC_AddAndList_RoundTripsRawRedirectURI(t *testing.T) { func TestOIDC_AddClient_OverwritesExistingByID(t *testing.T) { o := newTestOIDC(t) - assert.NoError(t, o.AddClient(OIDCClient{ID: "app1", Secret: "first", RedirectURI: "/a"})) - assert.NoError(t, o.AddClient(OIDCClient{ID: "app1", Secret: "second", RedirectURI: "/b"})) + assert.NoError(t, o.AddClient(OIDCClient{ID: "app1", Secret: "first", RedirectURIs: []string{"/a"}})) + assert.NoError(t, o.AddClient(OIDCClient{ID: "app1", Secret: "second", RedirectURIs: []string{"/b", "/c"}})) clients, err := o.Clients() assert.NoError(t, err) assert.Len(t, clients, 1) assert.Equal(t, "second", clients[0].Secret) - assert.Equal(t, "/b", clients[0].RedirectURI) + assert.Equal(t, []string{"/b", "/c"}, clients[0].RedirectURIs) } func TestOIDC_Clients_EmptyByDefault(t *testing.T) { @@ -54,3 +54,20 @@ func TestOIDC_Clients_EmptyByDefault(t *testing.T) { assert.NoError(t, err) assert.Empty(t, clients) } + +func TestOIDC_AddAndList_MultipleRedirectURIs(t *testing.T) { + o := newTestOIDC(t) + + err := o.AddClient(OIDCClient{ + ID: "app1", + Secret: "secret", + RedirectURIs: []string{"/auth/openid/callback", "/auth/openid/mobile-redirect"}, + RequirePkce: true, + }) + assert.NoError(t, err) + + clients, err := o.Clients() + assert.NoError(t, err) + assert.Len(t, clients, 1) + assert.Equal(t, []string{"/auth/openid/callback", "/auth/openid/mobile-redirect"}, clients[0].RedirectURIs) +} diff --git a/backend/go.mod b/backend/go.mod index d9e7ed17..c3d1db2f 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -10,17 +10,19 @@ require ( github.com/gorilla/sessions v1.2.1 github.com/hashicorp/go-retryablehttp v0.7.7 github.com/otiai10/copy v1.7.0 - github.com/prometheus/procfs v0.7.3 + github.com/pressly/goose/v3 v3.27.1 + github.com/prometheus/procfs v0.20.1 github.com/ricochet2200/go-disk-usage/du v0.0.0-20210707232629-ac9918953285 github.com/shirou/gopsutil/v3 v3.24.5 github.com/spf13/cobra v1.1.1 - github.com/stretchr/testify v1.9.0 + github.com/stretchr/testify v1.11.1 github.com/syncloud/golib v1.1.15 go.uber.org/zap v1.25.0 - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 + golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f golang.org/x/image v0.23.0 + golang.org/x/sys v0.43.0 gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.47.0 + modernc.org/sqlite v1.49.1 periph.io/x/conn/v3 v3.7.1 periph.io/x/devices/v3 v3.7.3 periph.io/x/host/v3 v3.8.3 @@ -38,26 +40,27 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-isatty v0.0.21 // indirect + github.com/mfridman/interpolate v0.0.2 // indirect github.com/miekg/dns v1.1.62 // indirect github.com/ncruces/go-strftime v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/sethvargo/go-retry v0.3.0 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.uber.org/multierr v1.10.0 // indirect - golang.org/x/crypto v0.48.0 // indirect - golang.org/x/mod v0.33.0 // indirect - golang.org/x/net v0.50.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.42.0 // indirect - golang.org/x/text v0.34.0 // indirect - golang.org/x/tools v0.42.0 // indirect - modernc.org/libc v1.70.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/crypto v0.50.0 // indirect + golang.org/x/mod v0.35.0 // indirect + golang.org/x/net v0.53.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/text v0.36.0 // indirect + golang.org/x/tools v0.44.0 // indirect + modernc.org/libc v1.72.1 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.11.0 // indirect ) diff --git a/backend/go.sum b/backend/go.sum index 90187e41..df87883e 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -83,10 +83,9 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -163,9 +162,11 @@ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaO github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs= +github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= +github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= @@ -200,6 +201,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/pressly/goose/v3 v3.27.1 h1:6uEvcprBybDmW4hcz3gYujhARhye+GoWKhEWyzD5sh4= +github.com/pressly/goose/v3 v3.27.1/go.mod h1:maruOxsPnIG2yHHyo8UqKWXYKFcH7Q76csUV7+7KYoM= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= @@ -208,8 +211,8 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= +github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= @@ -220,6 +223,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= +github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -246,8 +251,8 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syncloud/golib v1.1.15 h1:NuWw/BOJ+0maoU775HxrlpvXdAWrFvRnn5X2gPhRBxA= github.com/syncloud/golib v1.1.15/go.mod h1:XmmoqNuegLnl27FbmzLj60dTR/tN7c1X7Qp3uUPRC88= @@ -266,8 +271,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= -go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= @@ -277,15 +282,15 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= +golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM= +golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.23.0 h1:HseQ7c2OpPKTPVzNjG5fwJsOTCiiwS4QdsYi5XU6H68= @@ -301,8 +306,8 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= -golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -318,8 +323,8 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= +golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -328,9 +333,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -347,21 +351,19 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= -golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -381,8 +383,8 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= -golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= +golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= +golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -423,10 +425,10 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= -modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.32.0 h1:hjG66bI/kqIPX1b2yT6fr/jt+QedtP2fqojG2VrFuVw= -modernc.org/ccgo/v4 v4.32.0/go.mod h1:6F08EBCx5uQc38kMGl+0Nm0oWczoo1c7cgpzEry7Uc0= +modernc.org/cc/v4 v4.28.1 h1:XpLbkYVQ24E8tX5u8+yWGvaxerxkR/S4zqxI8ZoSBuc= +modernc.org/cc/v4 v4.28.1/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI= +modernc.org/ccgo/v4 v4.33.0 h1:dspBCm75jsj8Y/ufwAMVfe375L2iYdMyQ2QG/v3hL54= +modernc.org/ccgo/v4 v4.33.0/go.mod h1:+RhXBoRYzRwaH21mV/aj6XvQRDtfjcZfAlPMsQo8CR0= modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= @@ -435,18 +437,18 @@ modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo= modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.70.0 h1:U58NawXqXbgpZ/dcdS9kMshu08aiA6b7gusEusqzNkw= -modernc.org/libc v1.70.0/go.mod h1:OVmxFGP1CI/Z4L3E0Q3Mf1PDE0BucwMkcXjjLntvHJo= +modernc.org/libc v1.72.1 h1:db1xwJ6u1kE3KHTFTTbe2GCrczHPKzlURP0aDC4NGD0= +modernc.org/libc v1.72.1/go.mod h1:HRMiC/PhPGLIPM7GzAFCbI+oSgE3dhZ8FWftmRrHVlY= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= -modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= +modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.47.0 h1:R1XyaNpoW4Et9yly+I2EeX7pBza/w+pmYee/0HJDyKk= -modernc.org/sqlite v1.47.0/go.mod h1:hWjRO6Tj/5Ik8ieqxQybiEOUXy0NJFNp2tpvVpKlvig= +modernc.org/sqlite v1.49.1 h1:dYGHTKcX1sJ+EQDnUzvz4TJ5GbuvhNJa8Fg6ElGx73U= +modernc.org/sqlite v1.49.1/go.mod h1:m0w8xhwYUVY3H6pSDwc3gkJ/irZT/0YEXwBlhaxQEew= modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= diff --git a/backend/rest/api.go b/backend/rest/api.go index 70dda418..b251b674 100644 --- a/backend/rest/api.go +++ b/backend/rest/api.go @@ -30,7 +30,7 @@ type Systemd interface { } type WebAuth interface { - RegisterOIDCClient(id string, redirectURI string, requirePkce bool, tokenEndpointAuthMethod string) (string, error) + RegisterOIDCClient(id string, redirectURIs []string, requirePkce bool, tokenEndpointAuthMethod string) (string, error) } type Api struct { @@ -138,9 +138,10 @@ func (a *Api) RegisterOIDCClient(req *http.Request) (interface{}, error) { if err != nil { return nil, err } + redirectURIs := req.Form["redirect_uri"] password, err := a.webAuth.RegisterOIDCClient( req.FormValue("id"), - req.FormValue("redirect_uri"), + redirectURIs, req.FormValue("require_pkce") == "true", req.FormValue("token_endpoint_auth_method"), ) diff --git a/config/authelia/config.yml b/config/authelia/config.yml index a52ccb7d..f19291fa 100644 --- a/config/authelia/config.yml +++ b/config/authelia/config.yml @@ -816,7 +816,9 @@ identity_providers: public: false authorization_policy: '{{ if $.TwoFactorEnabled }}two_factor{{ else }}one_factor{{ end }}' redirect_uris: - - '{{ .RedirectURI }}' +{{- range .RedirectURIs }} + - '{{ . }}' +{{- end }} scopes: - 'openid' - 'email'