mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-30 02:46:30 +02:00
authenticate: support hot reloaded config (#984)
By implementinng OptionsUpdater interface. Fixes #982
This commit is contained in:
parent
eaa0c980d2
commit
17ba595ced
5 changed files with 41 additions and 9 deletions
|
@ -9,6 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"gopkg.in/square/go-jose.v2"
|
"gopkg.in/square/go-jose.v2"
|
||||||
|
|
||||||
|
@ -25,6 +26,7 @@ import (
|
||||||
"github.com/pomerium/pomerium/internal/httputil"
|
"github.com/pomerium/pomerium/internal/httputil"
|
||||||
"github.com/pomerium/pomerium/internal/identity"
|
"github.com/pomerium/pomerium/internal/identity"
|
||||||
"github.com/pomerium/pomerium/internal/identity/oauth"
|
"github.com/pomerium/pomerium/internal/identity/oauth"
|
||||||
|
"github.com/pomerium/pomerium/internal/log"
|
||||||
"github.com/pomerium/pomerium/internal/sessions"
|
"github.com/pomerium/pomerium/internal/sessions"
|
||||||
"github.com/pomerium/pomerium/internal/sessions/cookie"
|
"github.com/pomerium/pomerium/internal/sessions/cookie"
|
||||||
"github.com/pomerium/pomerium/internal/sessions/header"
|
"github.com/pomerium/pomerium/internal/sessions/header"
|
||||||
|
@ -105,6 +107,8 @@ type Authenticate struct {
|
||||||
// userClient is used to update users
|
// userClient is used to update users
|
||||||
userClient user.UserServiceClient
|
userClient user.UserServiceClient
|
||||||
|
|
||||||
|
// guard administrator below.
|
||||||
|
administratorMu sync.Mutex
|
||||||
// administrators keeps track of administrator users.
|
// administrators keeps track of administrator users.
|
||||||
administrator map[string]struct{}
|
administrator map[string]struct{}
|
||||||
|
|
||||||
|
@ -184,10 +188,6 @@ func New(opts config.Options) (*Authenticate, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
administrator := make(map[string]struct{}, len(opts.Administrators))
|
|
||||||
for _, admin := range opts.Administrators {
|
|
||||||
administrator[admin] = struct{}{}
|
|
||||||
}
|
|
||||||
a := &Authenticate{
|
a := &Authenticate{
|
||||||
RedirectURL: redirectURL,
|
RedirectURL: redirectURL,
|
||||||
// shared state
|
// shared state
|
||||||
|
@ -208,7 +208,6 @@ func New(opts config.Options) (*Authenticate, error) {
|
||||||
dataBrokerClient: dataBrokerClient,
|
dataBrokerClient: dataBrokerClient,
|
||||||
sessionClient: sessionClient,
|
sessionClient: sessionClient,
|
||||||
userClient: userClient,
|
userClient: userClient,
|
||||||
administrator: administrator,
|
|
||||||
jwk: &jose.JSONWebKeySet{},
|
jwk: &jose.JSONWebKeySet{},
|
||||||
templates: template.Must(frontend.NewTemplates()),
|
templates: template.Must(frontend.NewTemplates()),
|
||||||
}
|
}
|
||||||
|
@ -227,3 +226,26 @@ func New(opts config.Options) (*Authenticate, error) {
|
||||||
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *Authenticate) setAdminUsers(opts *config.Options) {
|
||||||
|
a.administratorMu.Lock()
|
||||||
|
defer a.administratorMu.Unlock()
|
||||||
|
|
||||||
|
a.administrator = make(map[string]struct{}, len(opts.Administrators))
|
||||||
|
for _, admin := range opts.Administrators {
|
||||||
|
a.administrator[admin] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateOptions implements the OptionsUpdater interface and updates internal
|
||||||
|
// structures based on config.Options
|
||||||
|
func (a *Authenticate) UpdateOptions(opts config.Options) error {
|
||||||
|
if a == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Info().Str("checksum", fmt.Sprintf("%x", opts.Checksum())).Msg("authenticate: updating options")
|
||||||
|
a.setAdminUsers(&opts)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -156,6 +156,7 @@ func TestIsAdmin(t *testing.T) {
|
||||||
opts := newTestOptions(t)
|
opts := newTestOptions(t)
|
||||||
opts.Administrators = tc.admins
|
opts.Administrators = tc.admins
|
||||||
a, err := New(*opts)
|
a, err := New(*opts)
|
||||||
|
assert.NoError(t, a.UpdateOptions(*opts))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.True(t, a.isAdmin(tc.user) == tc.isAdmin)
|
assert.True(t, a.isAdmin(tc.user) == tc.isAdmin)
|
||||||
})
|
})
|
||||||
|
|
|
@ -459,6 +459,9 @@ func (a *Authenticate) deleteSession(ctx context.Context, sessionID string) erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Authenticate) isAdmin(user string) bool {
|
func (a *Authenticate) isAdmin(user string) bool {
|
||||||
|
a.administratorMu.Lock()
|
||||||
|
defer a.administratorMu.Unlock()
|
||||||
|
|
||||||
_, ok := a.administrator[user]
|
_, ok := a.administrator[user]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,14 @@
|
||||||
|
|
||||||
### New
|
### New
|
||||||
|
|
||||||
- config: add remove_request_headers @cuonglm [GH-702]
|
- config: add remove_request_headers @cuonglm [GH-822]
|
||||||
- config: change default log level to INFO @cuonglm [GH-902]
|
- config: change default log level to INFO @cuonglm [GH-902]
|
||||||
- config: add pass_identity_headers @cuonglm [GH-903]
|
- config: add pass_identity_headers @cuonglm [GH-903]
|
||||||
|
- authenticate: allow hot reloaded admin users config @cuonglm [GH-984]
|
||||||
|
|
||||||
### Changes
|
### Changes
|
||||||
|
|
||||||
- proxy: do not set X-Pomerium-Jwt-Assertion/X-Pomerium-Claim-* headers by default [GH-903]
|
- proxy: do not set X-Pomerium-Jwt-Assertion/X-Pomerium-Claim-* headers by default @cuonglm [GH-903]
|
||||||
|
|
||||||
## v0.9.1
|
## v0.9.1
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ func Run(ctx context.Context, configFile string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// add services
|
// add services
|
||||||
if err := setupAuthenticate(opt, controlPlane); err != nil {
|
if err := setupAuthenticate(opt, controlPlane, &optionsUpdaters); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var authorizeServer *authorize.Authorize
|
var authorizeServer *authorize.Authorize
|
||||||
|
@ -132,7 +132,7 @@ func Run(ctx context.Context, configFile string) error {
|
||||||
return eg.Wait()
|
return eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupAuthenticate(opt *config.Options, controlPlane *controlplane.Server) error {
|
func setupAuthenticate(opt *config.Options, controlPlane *controlplane.Server, optionsUpdaters *[]config.OptionsUpdater) error {
|
||||||
if !config.IsAuthenticate(opt.Services) {
|
if !config.IsAuthenticate(opt.Services) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -141,6 +141,11 @@ func setupAuthenticate(opt *config.Options, controlPlane *controlplane.Server) e
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating authenticate service: %w", err)
|
return fmt.Errorf("error creating authenticate service: %w", err)
|
||||||
}
|
}
|
||||||
|
*optionsUpdaters = append(*optionsUpdaters, svc)
|
||||||
|
err = svc.UpdateOptions(*opt)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating authenticate options: %w", err)
|
||||||
|
}
|
||||||
host := urlutil.StripPort(opt.GetAuthenticateURL().Host)
|
host := urlutil.StripPort(opt.GetAuthenticateURL().Host)
|
||||||
sr := controlPlane.HTTPRouter.Host(host).Subrouter()
|
sr := controlPlane.HTTPRouter.Host(host).Subrouter()
|
||||||
svc.Mount(sr)
|
svc.Mount(sr)
|
||||||
|
|
Loading…
Add table
Reference in a new issue