mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-07 05:57:02 +00:00
Add a file-based session cache.
Signed-off-by: Matt Moyer <moyerm@vmware.com>
This commit is contained in:
@@ -5,12 +5,16 @@ package cmd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientauthenticationv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
|
||||
"k8s.io/klog/v2/klogr"
|
||||
|
||||
"go.pinniped.dev/internal/oidcclient"
|
||||
"go.pinniped.dev/internal/oidcclient/filesession"
|
||||
)
|
||||
|
||||
//nolint: gochecknoinits
|
||||
@@ -26,23 +30,42 @@ func oidcLoginCommand(loginFunc func(issuer string, clientID string, opts ...oid
|
||||
Short: "Login using an OpenID Connect provider",
|
||||
SilenceUsage: true,
|
||||
}
|
||||
issuer string
|
||||
clientID string
|
||||
listenPort uint16
|
||||
scopes []string
|
||||
skipBrowser bool
|
||||
issuer string
|
||||
clientID string
|
||||
listenPort uint16
|
||||
scopes []string
|
||||
skipBrowser bool
|
||||
sessionCachePath string
|
||||
debugSessionCache bool
|
||||
)
|
||||
cmd.Flags().StringVar(&issuer, "issuer", "", "OpenID Connect issuer URL.")
|
||||
cmd.Flags().StringVar(&clientID, "client-id", "", "OpenID Connect client ID.")
|
||||
cmd.Flags().Uint16Var(&listenPort, "listen-port", 0, "TCP port for localhost listener (authorization code flow only).")
|
||||
cmd.Flags().StringSliceVar(&scopes, "scopes", []string{"offline_access", "openid", "email", "profile"}, "OIDC scopes to request during login.")
|
||||
cmd.Flags().BoolVar(&skipBrowser, "skip-browser", false, "Skip opening the browser (just print the URL).")
|
||||
cmd.Flags().StringVar(&sessionCachePath, "session-cache", filepath.Join(mustGetConfigDir(), "sessions.yaml"), "Path to session cache file.")
|
||||
cmd.Flags().BoolVar(&debugSessionCache, "debug-session-cache", false, "Print debug logs related to the session cache.")
|
||||
mustMarkHidden(&cmd, "debug-session-cache")
|
||||
mustMarkRequired(&cmd, "issuer", "client-id")
|
||||
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
// Initialize the session cache.
|
||||
var sessionOptions []filesession.Option
|
||||
|
||||
// If the hidden --debug-session-cache option is passed, log all the errors from the session cache with klog.
|
||||
if debugSessionCache {
|
||||
logger := klogr.New().WithName("session")
|
||||
sessionOptions = append(sessionOptions, filesession.WithErrorReporter(func(err error) {
|
||||
logger.Error(err, "error during session cache operation")
|
||||
}))
|
||||
}
|
||||
sessionCache := filesession.New(sessionCachePath, sessionOptions...)
|
||||
|
||||
// Initialize the login handler.
|
||||
opts := []oidcclient.Option{
|
||||
oidcclient.WithContext(cmd.Context()),
|
||||
oidcclient.WithScopes(scopes),
|
||||
oidcclient.WithSessionCache(sessionCache),
|
||||
}
|
||||
|
||||
if listenPort != 0 {
|
||||
@@ -76,3 +99,20 @@ func oidcLoginCommand(loginFunc func(issuer string, clientID string, opts ...oid
|
||||
}
|
||||
return &cmd
|
||||
}
|
||||
|
||||
// mustGetConfigDir returns a directory that follows the XDG base directory convention:
|
||||
// $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should
|
||||
// be stored. If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME/.config should be used.
|
||||
// [1] https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
func mustGetConfigDir() string {
|
||||
const xdgAppName = "pinniped"
|
||||
|
||||
if path := os.Getenv("XDG_CONFIG_HOME"); path != "" {
|
||||
return filepath.Join(path, xdgAppName)
|
||||
}
|
||||
home, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return filepath.Join(home, ".config", xdgAppName)
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
func TestLoginOIDCCommand(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfgDir := mustGetConfigDir()
|
||||
|
||||
time1 := time.Date(3020, 10, 12, 13, 14, 15, 16, time.UTC)
|
||||
|
||||
tests := []struct {
|
||||
@@ -40,12 +42,13 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
oidc --issuer ISSUER --client-id CLIENT_ID [flags]
|
||||
|
||||
Flags:
|
||||
--client-id string OpenID Connect client ID.
|
||||
-h, --help help for oidc
|
||||
--issuer string OpenID Connect issuer URL.
|
||||
--listen-port uint16 TCP port for localhost listener (authorization code flow only).
|
||||
--scopes strings OIDC scopes to request during login. (default [offline_access,openid,email,profile])
|
||||
--skip-browser Skip opening the browser (just print the URL).
|
||||
--client-id string OpenID Connect client ID.
|
||||
-h, --help help for oidc
|
||||
--issuer string OpenID Connect issuer URL.
|
||||
--listen-port uint16 TCP port for localhost listener (authorization code flow only).
|
||||
--scopes strings OIDC scopes to request during login. (default [offline_access,openid,email,profile])
|
||||
--session-cache string Path to session cache file. (default "` + cfgDir + `/sessions.yaml")
|
||||
--skip-browser Skip opening the browser (just print the URL).
|
||||
`),
|
||||
},
|
||||
{
|
||||
@@ -64,7 +67,7 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
},
|
||||
wantIssuer: "test-issuer",
|
||||
wantClientID: "test-client-id",
|
||||
wantOptionsCount: 2,
|
||||
wantOptionsCount: 3,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
||||
},
|
||||
{
|
||||
@@ -74,10 +77,11 @@ func TestLoginOIDCCommand(t *testing.T) {
|
||||
"--issuer", "test-issuer",
|
||||
"--skip-browser",
|
||||
"--listen-port", "1234",
|
||||
"--debug-session-cache",
|
||||
},
|
||||
wantIssuer: "test-issuer",
|
||||
wantClientID: "test-client-id",
|
||||
wantOptionsCount: 4,
|
||||
wantOptionsCount: 5,
|
||||
wantStdout: `{"kind":"ExecCredential","apiVersion":"client.authentication.k8s.io/v1beta1","spec":{},"status":{"expirationTimestamp":"3020-10-12T13:14:15Z","token":"test-id-token"}}` + "\n",
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user