Skip to content

Commit 8bde63c

Browse files
Merge pull request #13276 from stlaz/direct_oidc_config
AUTH-440: expand options for the OIDC authenticator
2 parents a11a690 + 4f41023 commit 8bde63c

10 files changed

Lines changed: 286 additions & 198 deletions

File tree

cmd/bridge/config/auth/authoptions.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"net/url"
99
"os"
1010

11+
"github.com/coreos/pkg/flagutil"
12+
1113
utilerrors "k8s.io/apimachinery/pkg/util/errors"
1214
"k8s.io/client-go/rest"
1315
"k8s.io/klog"
@@ -28,6 +30,8 @@ type AuthOptions struct {
2830
ClientSecretFilePath string
2931
CAFilePath string
3032

33+
ExtraScopes flagutil.StringSliceFlag
34+
3135
InactivityTimeoutSeconds int
3236
LogoutRedirect string
3337
}
@@ -44,6 +48,8 @@ type completedOptions struct {
4448
ClientSecret string
4549
CAFilePath string
4650

51+
ExtraScopes []string
52+
4753
InactivityTimeoutSeconds int
4854
LogoutRedirectURL *url.URL
4955
}
@@ -60,19 +66,27 @@ func (c *AuthOptions) AddFlags(fs *flag.FlagSet) {
6066
fs.StringVar(&c.ClientSecretFilePath, "user-auth-oidc-client-secret-file", "", "File containing the OIDC OAuth2 Client Secret.")
6167
fs.StringVar(&c.CAFilePath, "user-auth-oidc-ca-file", "", "Path to a PEM file for the OIDC/OAuth2 issuer CA.")
6268

69+
fs.Var(&c.ExtraScopes, "user-auth-oidc-token-scopes", "Comma-separated list of extra scopes to request ID tokens with")
70+
6371
fs.IntVar(&c.InactivityTimeoutSeconds, "inactivity-timeout", 0, "Number of seconds, after which user will be logged out if inactive. Ignored if less than 300 seconds (5 minutes).")
6472
fs.StringVar(&c.LogoutRedirect, "user-auth-logout-redirect", "", "Optional redirect URL on logout needed for some single sign-on identity providers.")
6573
}
6674

6775
func (c *AuthOptions) ApplyConfig(config *serverconfig.Auth) {
76+
setIfUnset(&c.AuthType, config.AuthType)
6877
setIfUnset(&c.ClientID, config.ClientID)
78+
setIfUnset(&c.IssuerURL, config.OIDCIssuer)
6979
setIfUnset(&c.ClientSecretFilePath, config.ClientSecretFile)
7080
setIfUnset(&c.CAFilePath, config.OAuthEndpointCAFile)
7181
setIfUnset(&c.LogoutRedirect, config.LogoutRedirect)
7282

7383
if c.InactivityTimeoutSeconds == 0 {
7484
c.InactivityTimeoutSeconds = config.InactivityTimeoutSeconds
7585
}
86+
87+
if len(c.ExtraScopes) == 0 {
88+
c.ExtraScopes = config.OIDCExtraScopes
89+
}
7690
}
7791

7892
func (c *AuthOptions) Complete(k8sAuthType string) (*CompletedOptions, error) {
@@ -94,6 +108,7 @@ func (c *AuthOptions) Complete(k8sAuthType string) (*CompletedOptions, error) {
94108
AuthType: c.AuthType,
95109
ClientID: c.ClientID,
96110
ClientSecret: c.ClientSecret,
111+
ExtraScopes: c.ExtraScopes,
97112
CAFilePath: c.CAFilePath,
98113
InactivityTimeoutSeconds: c.InactivityTimeoutSeconds,
99114
}
@@ -155,6 +170,10 @@ func (c *AuthOptions) Validate(k8sAuthType string) []error {
155170
errs = append(errs, flags.NewInvalidFlagError("user-auth-oidc-issuer-url", "cannot be used with --user-auth=\"openshift\""))
156171
}
157172

173+
if len(c.ExtraScopes) > 0 {
174+
errs = append(errs, flags.NewInvalidFlagError("user-auth-oidc-token-scopes", "cannot be used with --user-auth=\"openshift\""))
175+
}
176+
158177
case "oidc":
159178
if len(c.IssuerURL) == 0 {
160179
errs = append(errs, fmt.Errorf("--user-auth-oidc-issuer-url must be set if --user-auth=oidc"))
@@ -220,20 +239,17 @@ func (c *completedOptions) getAuthenticator(
220239
useSecureCookies = baseURL.Scheme == "https"
221240
)
222241

223-
scopes := []string{"openid", "email", "profile", "groups"}
224-
authSource := auth.AuthSourceTectonic
242+
var scopes []string
243+
authSource := auth.AuthSourceOIDC
225244

226245
if c.AuthType == "openshift" {
227-
// Scopes come from OpenShift documentation
228-
// https://access.redhat.com/documentation/en-us/openshift_container_platform/4.9/html/authentication_and_authorization/using-service-accounts-as-oauth-client
229-
//
230-
// TODO(ericchiang): Support other scopes like view only permissions.
231246
scopes = []string{"user:full"}
232247
authSource = auth.AuthSourceOpenShift
233248

234249
userAuthOIDCIssuerURL = k8sEndpoint
235250
} else {
236251
userAuthOIDCIssuerURL = c.IssuerURL
252+
scopes = append(c.ExtraScopes, "openid")
237253

238254
}
239255

pkg/auth/asynccache.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package auth
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"sync"
7+
"time"
8+
9+
"k8s.io/apimachinery/pkg/util/wait"
10+
"k8s.io/klog"
11+
)
12+
13+
type cachingFuncType[T any] func(ctx context.Context) (T, error)
14+
15+
type AsyncCache[T any] struct {
16+
reloadPeriod time.Duration
17+
18+
itemRWLock sync.RWMutex
19+
cachedItem T
20+
cachingFunc cachingFuncType[T]
21+
}
22+
23+
func NewAsyncCache[T any](ctx context.Context, reloadPeriod time.Duration, cachingFunc cachingFuncType[T]) (*AsyncCache[T], error) {
24+
c := &AsyncCache[T]{
25+
reloadPeriod: reloadPeriod,
26+
itemRWLock: sync.RWMutex{},
27+
cachingFunc: cachingFunc,
28+
}
29+
30+
item, err := cachingFunc(ctx)
31+
if err != nil {
32+
return nil, fmt.Errorf("failed to setup an async cache - caching func returned error: %w", err)
33+
}
34+
35+
c.cachedItem = item
36+
37+
return c, nil
38+
}
39+
40+
func (c *AsyncCache[T]) runCache(ctx context.Context) {
41+
item, err := c.cachingFunc(ctx)
42+
if err != nil {
43+
klog.Errorf("failed a caching attempt: %v", err)
44+
return
45+
}
46+
47+
c.itemRWLock.Lock()
48+
defer c.itemRWLock.Unlock()
49+
c.cachedItem = item
50+
}
51+
52+
func (c *AsyncCache[T]) GetItem() T {
53+
c.itemRWLock.RLock()
54+
defer c.itemRWLock.RUnlock()
55+
return c.cachedItem
56+
}
57+
58+
func (c *AsyncCache[T]) Run(ctx context.Context) {
59+
go wait.UntilWithContext(ctx, c.runCache, c.reloadPeriod)
60+
}

0 commit comments

Comments
 (0)