2022-04-27 15:53:53 +00:00
// Copyright 2020-2022 the Pinniped contributors. All Rights Reserved.
2020-10-06 00:09:51 +00:00
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
2020-12-15 00:38:19 +00:00
"context"
2020-11-16 17:54:13 +00:00
"crypto/x509"
2020-12-15 00:38:19 +00:00
"encoding/base64"
2020-10-06 22:27:36 +00:00
"encoding/json"
2020-11-16 17:54:13 +00:00
"fmt"
"net/http"
2020-10-21 17:54:26 +00:00
"os"
"path/filepath"
2021-08-12 17:00:18 +00:00
"strings"
2020-12-15 00:38:19 +00:00
"time"
2020-10-06 00:09:51 +00:00
2021-01-20 17:54:44 +00:00
"github.com/coreos/go-oidc/v3/oidc"
2020-10-06 00:09:51 +00:00
"github.com/spf13/cobra"
2020-10-06 22:27:36 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2020-12-15 00:38:19 +00:00
clientauthv1beta1 "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1"
2020-10-06 00:09:51 +00:00
2021-08-18 00:50:02 +00:00
idpdiscoveryv1alpha1 "go.pinniped.dev/generated/latest/apis/supervisor/idpdiscovery/v1alpha1"
2021-04-08 15:48:45 +00:00
"go.pinniped.dev/internal/execcredcache"
2021-02-19 18:21:10 +00:00
"go.pinniped.dev/internal/groupsuffix"
2021-10-20 11:59:24 +00:00
"go.pinniped.dev/internal/net/phttp"
2021-04-06 22:13:27 +00:00
"go.pinniped.dev/internal/plog"
2020-12-15 00:38:19 +00:00
"go.pinniped.dev/pkg/conciergeclient"
2020-11-17 18:46:54 +00:00
"go.pinniped.dev/pkg/oidcclient"
"go.pinniped.dev/pkg/oidcclient/filesession"
2020-11-30 23:02:03 +00:00
"go.pinniped.dev/pkg/oidcclient/oidctypes"
2020-10-06 00:09:51 +00:00
)
2022-06-02 17:30:03 +00:00
const (
// The user may override the flow selection made by `--upstream-identity-provider-flow` using an env var.
// This allows the user to override their default flow selected inside their Pinniped-compatible kubeconfig file.
// A user might want to use this env var, for example, to choose the "browser_authcode" flow when using a kubeconfig
// which specifies "cli_password" when using an IDE plugin where there is no interactive CLI available. This allows
// the user to use one kubeconfig file for both flows.
upstreamIdentityProviderFlowEnvVarName = "PINNIPED_UPSTREAM_IDENTITY_PROVIDER_FLOW"
)
2022-08-24 21:45:55 +00:00
//nolint:gochecknoinits
2020-10-06 00:09:51 +00:00
func init ( ) {
2020-12-15 00:38:19 +00:00
loginCmd . AddCommand ( oidcLoginCommand ( oidcLoginCommandRealDeps ( ) ) )
2020-10-06 00:09:51 +00:00
}
2020-12-15 00:38:19 +00:00
type oidcLoginCommandDeps struct {
2021-04-16 21:38:05 +00:00
lookupEnv func ( string ) ( string , bool )
2020-12-15 00:38:19 +00:00
login func ( string , string , ... oidcclient . Option ) ( * oidctypes . Token , error )
exchangeToken func ( context . Context , * conciergeclient . Client , string ) ( * clientauthv1beta1 . ExecCredential , error )
}
func oidcLoginCommandRealDeps ( ) oidcLoginCommandDeps {
return oidcLoginCommandDeps {
2021-04-16 21:38:05 +00:00
lookupEnv : os . LookupEnv ,
login : oidcclient . Login ,
2020-12-15 00:38:19 +00:00
exchangeToken : func ( ctx context . Context , client * conciergeclient . Client , token string ) ( * clientauthv1beta1 . ExecCredential , error ) {
return client . ExchangeToken ( ctx , token )
} ,
}
}
type oidcLoginFlags struct {
2021-04-17 01:30:31 +00:00
issuer string
clientID string
listenPort uint16
scopes [ ] string
skipBrowser bool
2021-07-09 03:26:21 +00:00
skipListen bool
2021-04-17 01:30:31 +00:00
sessionCachePath string
caBundlePaths [ ] string
caBundleData [ ] string
debugSessionCache bool
requestAudience string
conciergeEnabled bool
conciergeAuthenticatorType string
conciergeAuthenticatorName string
conciergeEndpoint string
conciergeCABundle string
conciergeAPIGroupSuffix string
credentialCachePath string
upstreamIdentityProviderName string
upstreamIdentityProviderType string
2021-08-12 17:00:18 +00:00
upstreamIdentityProviderFlow string
2020-12-15 00:38:19 +00:00
}
func oidcLoginCommand ( deps oidcLoginCommandDeps ) * cobra . Command {
2020-10-06 22:27:36 +00:00
var (
2021-02-09 18:59:32 +00:00
cmd = & cobra . Command {
2020-10-06 22:27:36 +00:00
Args : cobra . NoArgs ,
2020-12-15 00:38:19 +00:00
Use : "oidc --issuer ISSUER" ,
2020-10-06 22:27:36 +00:00
Short : "Login using an OpenID Connect provider" ,
SilenceUsage : true ,
}
2021-02-09 18:59:32 +00:00
flags oidcLoginFlags
conciergeNamespace string // unused now
2020-10-06 22:27:36 +00:00
)
2020-12-15 00:38:19 +00:00
cmd . Flags ( ) . StringVar ( & flags . issuer , "issuer" , "" , "OpenID Connect issuer URL" )
cmd . Flags ( ) . StringVar ( & flags . clientID , "client-id" , "pinniped-cli" , "OpenID Connect client ID" )
cmd . Flags ( ) . Uint16Var ( & flags . listenPort , "listen-port" , 0 , "TCP port for localhost listener (authorization code flow only)" )
2020-12-16 03:59:57 +00:00
cmd . Flags ( ) . StringSliceVar ( & flags . scopes , "scopes" , [ ] string { oidc . ScopeOfflineAccess , oidc . ScopeOpenID , "pinniped:request-audience" } , "OIDC scopes to request during login" )
2020-12-15 00:38:19 +00:00
cmd . Flags ( ) . BoolVar ( & flags . skipBrowser , "skip-browser" , false , "Skip opening the browser (just print the URL)" )
2021-07-09 03:26:21 +00:00
cmd . Flags ( ) . BoolVar ( & flags . skipListen , "skip-listen" , false , "Skip starting a localhost callback listener (manual copy/paste flow only)" )
2020-12-15 00:38:19 +00:00
cmd . Flags ( ) . StringVar ( & flags . sessionCachePath , "session-cache" , filepath . Join ( mustGetConfigDir ( ) , "sessions.yaml" ) , "Path to session cache file" )
cmd . Flags ( ) . StringSliceVar ( & flags . caBundlePaths , "ca-bundle" , nil , "Path to TLS certificate authority bundle (PEM format, optional, can be repeated)" )
2021-02-24 23:07:07 +00:00
cmd . Flags ( ) . StringSliceVar ( & flags . caBundleData , "ca-bundle-data" , nil , "Base64 encoded TLS certificate authority bundle (base64 encoded PEM format, optional, can be repeated)" )
2020-12-15 00:38:19 +00:00
cmd . Flags ( ) . BoolVar ( & flags . debugSessionCache , "debug-session-cache" , false , "Print debug logs related to the session cache" )
2020-12-16 03:59:57 +00:00
cmd . Flags ( ) . StringVar ( & flags . requestAudience , "request-audience" , "" , "Request a token with an alternate audience using RFC8693 token exchange" )
2021-02-24 23:07:07 +00:00
cmd . Flags ( ) . BoolVar ( & flags . conciergeEnabled , "enable-concierge" , false , "Use the Concierge to login" )
cmd . Flags ( ) . StringVar ( & conciergeNamespace , "concierge-namespace" , "pinniped-concierge" , "Namespace in which the Concierge was installed" )
2020-12-15 00:38:19 +00:00
cmd . Flags ( ) . StringVar ( & flags . conciergeAuthenticatorType , "concierge-authenticator-type" , "" , "Concierge authenticator type (e.g., 'webhook', 'jwt')" )
cmd . Flags ( ) . StringVar ( & flags . conciergeAuthenticatorName , "concierge-authenticator-name" , "" , "Concierge authenticator name" )
2021-02-24 23:07:07 +00:00
cmd . Flags ( ) . StringVar ( & flags . conciergeEndpoint , "concierge-endpoint" , "" , "API base for the Concierge endpoint" )
cmd . Flags ( ) . StringVar ( & flags . conciergeCABundle , "concierge-ca-bundle-data" , "" , "CA bundle to use when connecting to the Concierge" )
2021-02-19 18:21:10 +00:00
cmd . Flags ( ) . StringVar ( & flags . conciergeAPIGroupSuffix , "concierge-api-group-suffix" , groupsuffix . PinnipedDefaultSuffix , "Concierge API group suffix" )
2021-04-08 21:00:21 +00:00
cmd . Flags ( ) . StringVar ( & flags . credentialCachePath , "credential-cache" , filepath . Join ( mustGetConfigDir ( ) , "credentials.yaml" ) , "Path to cluster-specific credentials cache (\"\" disables the cache)" )
2021-04-17 01:30:31 +00:00
cmd . Flags ( ) . StringVar ( & flags . upstreamIdentityProviderName , "upstream-identity-provider-name" , "" , "The name of the upstream identity provider used during login with a Supervisor" )
2021-08-24 19:19:29 +00:00
cmd . Flags ( ) . StringVar ( & flags . upstreamIdentityProviderType , "upstream-identity-provider-type" , idpdiscoveryv1alpha1 . IDPTypeOIDC . String ( ) , fmt . Sprintf ( "The type of the upstream identity provider used during login with a Supervisor (e.g. '%s', '%s', '%s')" , idpdiscoveryv1alpha1 . IDPTypeOIDC , idpdiscoveryv1alpha1 . IDPTypeLDAP , idpdiscoveryv1alpha1 . IDPTypeActiveDirectory ) )
2021-08-18 00:50:02 +00:00
cmd . Flags ( ) . StringVar ( & flags . upstreamIdentityProviderFlow , "upstream-identity-provider-flow" , "" , fmt . Sprintf ( "The type of client flow to use with the upstream identity provider during login with a Supervisor (e.g. '%s', '%s')" , idpdiscoveryv1alpha1 . IDPFlowBrowserAuthcode , idpdiscoveryv1alpha1 . IDPFlowCLIPassword ) )
2020-12-15 00:38:19 +00:00
2021-07-09 03:26:21 +00:00
// --skip-listen is mainly needed for testing. We'll leave it hidden until we have a non-testing use case.
mustMarkHidden ( cmd , "skip-listen" )
2021-02-09 18:59:32 +00:00
mustMarkHidden ( cmd , "debug-session-cache" )
mustMarkRequired ( cmd , "issuer" )
2020-12-15 00:38:19 +00:00
cmd . RunE = func ( cmd * cobra . Command , args [ ] string ) error { return runOIDCLogin ( cmd , deps , flags ) }
2021-02-09 18:59:32 +00:00
mustMarkDeprecated ( cmd , "concierge-namespace" , "not needed anymore" )
mustMarkHidden ( cmd , "concierge-namespace" )
return cmd
2020-12-15 00:38:19 +00:00
}
2020-10-06 00:09:51 +00:00
2021-05-11 18:09:37 +00:00
func runOIDCLogin ( cmd * cobra . Command , deps oidcLoginCommandDeps , flags oidcLoginFlags ) error { //nolint:funlen
2022-04-16 02:43:53 +00:00
pLogger , err := SetLogLevel ( cmd . Context ( ) , deps . lookupEnv )
2021-04-08 17:14:29 +00:00
if err != nil {
plog . WarningErr ( "Received error while setting log level" , err )
}
2021-04-06 22:13:27 +00:00
2020-12-15 00:38:19 +00:00
// Initialize the session cache.
var sessionOptions [ ] filesession . Option
2020-10-21 17:54:26 +00:00
2022-04-16 02:43:53 +00:00
// If the hidden --debug-session-cache option is passed, log all the errors from the session cache.
2020-12-15 00:38:19 +00:00
if flags . debugSessionCache {
2022-04-16 02:43:53 +00:00
logger := plog . WithName ( "session" )
2020-12-15 00:38:19 +00:00
sessionOptions = append ( sessionOptions , filesession . WithErrorReporter ( func ( err error ) {
2022-04-16 02:43:53 +00:00
logger . Error ( "error during session cache operation" , err )
2020-12-15 00:38:19 +00:00
} ) )
}
sessionCache := filesession . New ( flags . sessionCachePath , sessionOptions ... )
2020-10-21 17:54:26 +00:00
2020-12-15 00:38:19 +00:00
// Initialize the login handler.
opts := [ ] oidcclient . Option {
oidcclient . WithContext ( cmd . Context ( ) ) ,
2022-08-24 21:45:55 +00:00
oidcclient . WithLogger ( plog . Logr ( ) ) , //nolint:staticcheck // old code with lots of log statements
2020-12-15 00:38:19 +00:00
oidcclient . WithScopes ( flags . scopes ) ,
oidcclient . WithSessionCache ( sessionCache ) ,
}
2020-10-06 00:09:51 +00:00
2020-12-15 00:38:19 +00:00
if flags . listenPort != 0 {
opts = append ( opts , oidcclient . WithListenPort ( flags . listenPort ) )
}
2020-10-06 00:09:51 +00:00
2020-12-15 00:38:19 +00:00
if flags . requestAudience != "" {
opts = append ( opts , oidcclient . WithRequestAudience ( flags . requestAudience ) )
}
2020-12-04 23:33:53 +00:00
2021-04-17 01:30:31 +00:00
if flags . upstreamIdentityProviderName != "" {
opts = append ( opts , oidcclient . WithUpstreamIdentityProvider (
flags . upstreamIdentityProviderName , flags . upstreamIdentityProviderType ) )
}
2021-08-18 00:50:02 +00:00
flowOpts , err := flowOptions (
idpdiscoveryv1alpha1 . IDPType ( flags . upstreamIdentityProviderType ) ,
idpdiscoveryv1alpha1 . IDPFlow ( flags . upstreamIdentityProviderFlow ) ,
2022-06-02 17:30:03 +00:00
deps ,
2021-08-18 00:50:02 +00:00
)
2021-08-12 17:00:18 +00:00
if err != nil {
return err
2021-04-17 01:30:31 +00:00
}
2021-08-12 17:00:18 +00:00
opts = append ( opts , flowOpts ... )
2021-04-17 01:30:31 +00:00
2020-12-15 00:38:19 +00:00
var concierge * conciergeclient . Client
if flags . conciergeEnabled {
var err error
concierge , err = conciergeclient . New (
conciergeclient . WithEndpoint ( flags . conciergeEndpoint ) ,
conciergeclient . WithBase64CABundle ( flags . conciergeCABundle ) ,
conciergeclient . WithAuthenticator ( flags . conciergeAuthenticatorType , flags . conciergeAuthenticatorName ) ,
2021-01-19 16:29:15 +00:00
conciergeclient . WithAPIGroupSuffix ( flags . conciergeAPIGroupSuffix ) ,
2020-12-15 00:38:19 +00:00
)
if err != nil {
2021-03-11 22:18:15 +00:00
return fmt . Errorf ( "invalid Concierge parameters: %w" , err )
2020-10-06 22:27:36 +00:00
}
2020-12-15 00:38:19 +00:00
}
2020-10-06 00:09:51 +00:00
2021-07-07 22:17:57 +00:00
// --skip-browser skips opening the browser.
2020-12-15 00:38:19 +00:00
if flags . skipBrowser {
2021-07-07 22:17:57 +00:00
opts = append ( opts , oidcclient . WithSkipBrowserOpen ( ) )
2020-12-15 00:38:19 +00:00
}
2020-11-16 17:54:13 +00:00
2021-07-09 03:26:21 +00:00
// --skip-listen skips starting the localhost callback listener.
if flags . skipListen {
opts = append ( opts , oidcclient . WithSkipListen ( ) )
}
2020-12-15 00:38:19 +00:00
if len ( flags . caBundlePaths ) > 0 || len ( flags . caBundleData ) > 0 {
client , err := makeClient ( flags . caBundlePaths , flags . caBundleData )
2020-10-06 22:27:36 +00:00
if err != nil {
return err
2020-10-06 00:09:51 +00:00
}
2020-12-15 00:38:19 +00:00
opts = append ( opts , oidcclient . WithClient ( client ) )
}
2021-04-08 22:00:14 +00:00
// Look up cached credentials based on a hash of all the CLI arguments and the cluster info.
2021-04-08 15:48:45 +00:00
cacheKey := struct {
2021-04-08 22:00:14 +00:00
Args [ ] string ` json:"args" `
ClusterInfo * clientauthv1beta1 . Cluster ` json:"cluster" `
2021-04-08 15:48:45 +00:00
} {
2021-04-08 22:00:14 +00:00
Args : os . Args [ 1 : ] ,
ClusterInfo : loadClusterInfo ( ) ,
2021-04-08 15:48:45 +00:00
}
var credCache * execcredcache . Cache
if flags . credentialCachePath != "" {
credCache = execcredcache . New ( flags . credentialCachePath )
if cred := credCache . Get ( cacheKey ) ; cred != nil {
2021-04-19 17:46:22 +00:00
pLogger . Debug ( "using cached cluster credential." )
2021-04-08 15:48:45 +00:00
return json . NewEncoder ( cmd . OutOrStdout ( ) ) . Encode ( cred )
}
}
2021-04-16 17:46:59 +00:00
pLogger . Debug ( "Performing OIDC login" , "issuer" , flags . issuer , "client id" , flags . clientID )
2020-12-15 00:38:19 +00:00
// Do the basic login to get an OIDC token.
token , err := deps . login ( flags . issuer , flags . clientID , opts ... )
if err != nil {
return fmt . Errorf ( "could not complete Pinniped login: %w" , err )
}
cred := tokenCredential ( token )
2021-03-11 22:14:56 +00:00
// If the concierge was configured, exchange the credential for a separate short-lived, cluster-specific credential.
if concierge != nil {
2021-04-16 17:46:59 +00:00
pLogger . Debug ( "Exchanging token for cluster credential" , "endpoint" , flags . conciergeEndpoint , "authenticator type" , flags . conciergeAuthenticatorType , "authenticator name" , flags . conciergeAuthenticatorName )
2021-03-11 22:14:56 +00:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 30 * time . Second )
defer cancel ( )
2020-12-15 00:38:19 +00:00
2021-03-11 22:14:56 +00:00
cred , err = deps . exchangeToken ( ctx , concierge , token . IDToken . Token )
2020-12-15 00:38:19 +00:00
if err != nil {
2021-03-11 22:18:15 +00:00
return fmt . Errorf ( "could not complete Concierge credential exchange: %w" , err )
2020-12-15 00:38:19 +00:00
}
2021-04-21 17:58:48 +00:00
pLogger . Debug ( "Successfully exchanged token for cluster credential." )
2021-04-07 22:30:29 +00:00
} else {
2021-04-16 17:46:59 +00:00
pLogger . Debug ( "No concierge configured, skipping token credential exchange" )
2021-01-26 19:39:42 +00:00
}
2021-04-08 15:48:45 +00:00
// If there was a credential cache, save the resulting credential for future use.
if credCache != nil {
2021-04-19 17:46:22 +00:00
pLogger . Debug ( "caching cluster credential for future use." )
2021-04-08 15:48:45 +00:00
credCache . Put ( cacheKey , cred )
}
2021-03-11 22:14:56 +00:00
return json . NewEncoder ( cmd . OutOrStdout ( ) ) . Encode ( cred )
2020-12-15 00:38:19 +00:00
}
2021-02-24 23:07:07 +00:00
2022-06-02 17:30:03 +00:00
func flowOptions (
requestedIDPType idpdiscoveryv1alpha1 . IDPType ,
requestedFlow idpdiscoveryv1alpha1 . IDPFlow ,
deps oidcLoginCommandDeps ,
) ( [ ] oidcclient . Option , error ) {
2021-08-12 17:00:18 +00:00
useCLIFlow := [ ] oidcclient . Option { oidcclient . WithCLISendingCredentials ( ) }
2022-06-02 17:30:03 +00:00
// If the env var is set to override the --upstream-identity-provider-type flag, then override it.
flowOverride , hasFlowOverride := deps . lookupEnv ( upstreamIdentityProviderFlowEnvVarName )
flowSource := "--upstream-identity-provider-flow"
if hasFlowOverride {
requestedFlow = idpdiscoveryv1alpha1 . IDPFlow ( flowOverride )
flowSource = upstreamIdentityProviderFlowEnvVarName
}
2021-08-12 17:00:18 +00:00
switch requestedIDPType {
2021-08-18 00:50:02 +00:00
case idpdiscoveryv1alpha1 . IDPTypeOIDC :
2021-08-12 17:00:18 +00:00
switch requestedFlow {
2021-08-18 00:50:02 +00:00
case idpdiscoveryv1alpha1 . IDPFlowCLIPassword :
2021-08-12 17:00:18 +00:00
return useCLIFlow , nil
2021-08-18 00:50:02 +00:00
case idpdiscoveryv1alpha1 . IDPFlowBrowserAuthcode , "" :
2021-08-12 17:00:18 +00:00
return nil , nil // browser authcode flow is the default Option, so don't need to return an Option here
default :
return nil , fmt . Errorf (
2022-06-02 17:30:03 +00:00
"%s value not recognized for identity provider type %q: %s (supported values: %s)" ,
flowSource , requestedIDPType , requestedFlow ,
strings . Join ( [ ] string { idpdiscoveryv1alpha1 . IDPFlowBrowserAuthcode . String ( ) , idpdiscoveryv1alpha1 . IDPFlowCLIPassword . String ( ) } , ", " ) )
2021-08-12 17:00:18 +00:00
}
2021-08-24 19:19:29 +00:00
case idpdiscoveryv1alpha1 . IDPTypeLDAP , idpdiscoveryv1alpha1 . IDPTypeActiveDirectory :
2021-08-12 17:00:18 +00:00
switch requestedFlow {
2021-08-18 00:50:02 +00:00
case idpdiscoveryv1alpha1 . IDPFlowCLIPassword , "" :
2021-08-12 17:00:18 +00:00
return useCLIFlow , nil
2021-08-18 00:50:02 +00:00
case idpdiscoveryv1alpha1 . IDPFlowBrowserAuthcode :
2022-06-02 17:30:03 +00:00
return nil , nil // browser authcode flow is the default Option, so don't need to return an Option here
2021-08-12 17:00:18 +00:00
default :
return nil , fmt . Errorf (
2022-06-02 17:30:03 +00:00
"%s value not recognized for identity provider type %q: %s (supported values: %s)" ,
flowSource , requestedIDPType , requestedFlow ,
strings . Join ( [ ] string { idpdiscoveryv1alpha1 . IDPFlowCLIPassword . String ( ) , idpdiscoveryv1alpha1 . IDPFlowBrowserAuthcode . String ( ) } , ", " ) )
2021-08-12 17:00:18 +00:00
}
default :
// Surprisingly cobra does not support this kind of flag validation. See https://github.com/spf13/pflag/issues/236
return nil , fmt . Errorf (
"--upstream-identity-provider-type value not recognized: %s (supported values: %s)" ,
2021-08-24 19:19:29 +00:00
requestedIDPType ,
strings . Join ( [ ] string {
idpdiscoveryv1alpha1 . IDPTypeOIDC . String ( ) ,
idpdiscoveryv1alpha1 . IDPTypeLDAP . String ( ) ,
idpdiscoveryv1alpha1 . IDPTypeActiveDirectory . String ( ) ,
} , ", " ) ,
)
2021-08-12 17:00:18 +00:00
}
}
2020-12-15 00:38:19 +00:00
func makeClient ( caBundlePaths [ ] string , caBundleData [ ] string ) ( * http . Client , error ) {
pool := x509 . NewCertPool ( )
for _ , p := range caBundlePaths {
2022-08-24 21:45:55 +00:00
pem , err := os . ReadFile ( p )
2020-12-15 00:38:19 +00:00
if err != nil {
return nil , fmt . Errorf ( "could not read --ca-bundle: %w" , err )
}
pool . AppendCertsFromPEM ( pem )
}
for _ , d := range caBundleData {
pem , err := base64 . StdEncoding . DecodeString ( d )
if err != nil {
return nil , fmt . Errorf ( "could not read --ca-bundle-data: %w" , err )
}
pool . AppendCertsFromPEM ( pem )
}
2021-10-20 11:59:24 +00:00
return phttp . Default ( pool ) , nil
2020-12-15 00:38:19 +00:00
}
func tokenCredential ( token * oidctypes . Token ) * clientauthv1beta1 . ExecCredential {
cred := clientauthv1beta1 . ExecCredential {
TypeMeta : metav1 . TypeMeta {
Kind : "ExecCredential" ,
APIVersion : "client.authentication.k8s.io/v1beta1" ,
} ,
Status : & clientauthv1beta1 . ExecCredentialStatus {
Token : token . IDToken . Token ,
} ,
2020-10-06 00:09:51 +00:00
}
2020-12-15 00:38:19 +00:00
if ! token . IDToken . Expiry . IsZero ( ) {
cred . Status . ExpirationTimestamp = & token . IDToken . Expiry
}
return & cred
2020-10-06 00:09:51 +00:00
}
2020-10-21 17:54:26 +00:00
2022-04-16 02:43:53 +00:00
func SetLogLevel ( ctx context . Context , lookupEnv func ( string ) ( string , bool ) ) ( plog . Logger , error ) {
2021-04-16 21:38:05 +00:00
debug , _ := lookupEnv ( "PINNIPED_DEBUG" )
if debug == "true" {
2022-04-16 02:43:53 +00:00
err := plog . ValidateAndSetLogLevelAndFormatGlobally ( ctx , plog . LogSpec { Level : plog . LevelDebug , Format : plog . FormatCLI } )
2021-04-08 17:14:29 +00:00
if err != nil {
2021-04-16 17:46:59 +00:00
return nil , err
2021-04-08 17:14:29 +00:00
}
2021-04-06 22:13:27 +00:00
}
2022-04-16 02:43:53 +00:00
logger := plog . New ( ) . WithName ( "pinniped-login" )
2021-10-20 11:59:24 +00:00
return logger , nil
2021-04-06 22:13:27 +00:00
}
2022-08-24 21:45:55 +00:00
/ *
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
* /
2020-10-21 17:54:26 +00:00
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 )
}