mirror of
https://github.com/int128/kubelogin.git
synced 2026-02-14 16:39:51 +00:00
Refactor (#158)
* Refactor: template rendering * Refactor: rename DecodedIDToken fields * Refactor: expand command options * Refactor: improve help messages
This commit is contained in:
10
README.md
10
README.md
@@ -82,21 +82,21 @@ If you are looking for a specific version, see [the release tags](https://github
|
|||||||
Kubelogin supports the following options:
|
Kubelogin supports the following options:
|
||||||
|
|
||||||
```
|
```
|
||||||
% kubelogin get-token -h
|
% kubectl oidc-login get-token -h
|
||||||
Run as a kubectl credential plugin
|
Run as a kubectl credential plugin
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
kubelogin get-token [flags]
|
kubelogin get-token [flags]
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--listen-port ints Port to bind to the local server. If multiple ports are given, it will try the ports in order (default [8000,18000])
|
|
||||||
--skip-open-browser If true, it does not open the browser on authentication
|
|
||||||
--username string If set, perform the resource owner password credentials grant
|
|
||||||
--password string If set, use the password instead of asking it
|
|
||||||
--oidc-issuer-url string Issuer URL of the provider (mandatory)
|
--oidc-issuer-url string Issuer URL of the provider (mandatory)
|
||||||
--oidc-client-id string Client ID of the provider (mandatory)
|
--oidc-client-id string Client ID of the provider (mandatory)
|
||||||
--oidc-client-secret string Client secret of the provider
|
--oidc-client-secret string Client secret of the provider
|
||||||
--oidc-extra-scope strings Scopes to request to the provider
|
--oidc-extra-scope strings Scopes to request to the provider
|
||||||
|
--listen-port ints Port to bind to the local server. If multiple ports are given, it will try the ports in order (default [8000,18000])
|
||||||
|
--skip-open-browser If true, it does not open the browser on authentication
|
||||||
|
--username string If set, perform the resource owner password credentials grant
|
||||||
|
--password string If set, use the password instead of asking it
|
||||||
--certificate-authority string Path to a cert file for the certificate authority
|
--certificate-authority string Path to a cert file for the certificate authority
|
||||||
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
|
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
|
||||||
--token-cache-dir string Path to a directory for caching tokens (default "~/.kube/cache/oidc-login")
|
--token-cache-dir string Path to a directory for caching tokens (default "~/.kube/cache/oidc-login")
|
||||||
|
|||||||
@@ -78,38 +78,36 @@ If the refresh token has expired, kubelogin will proceed the authentication.
|
|||||||
Kubelogin supports the following options:
|
Kubelogin supports the following options:
|
||||||
|
|
||||||
```
|
```
|
||||||
% kubelogin -h
|
% kubectl oidc-login -h
|
||||||
Login to the OpenID Connect provider and update the kubeconfig
|
Login to the OpenID Connect provider.
|
||||||
|
|
||||||
|
You need to set up the OIDC provider, role binding, Kubernetes API server and kubeconfig.
|
||||||
|
Run the following command to show the setup instruction:
|
||||||
|
|
||||||
|
kubectl oidc-login setup
|
||||||
|
|
||||||
|
See https://github.com/int128/kubelogin for more.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
kubelogin [flags]
|
main [flags]
|
||||||
kubelogin [command]
|
main [command]
|
||||||
|
|
||||||
Examples:
|
|
||||||
# Login to the provider using the authorization code flow.
|
|
||||||
kubelogin
|
|
||||||
|
|
||||||
# Login to the provider using the resource owner password credentials flow.
|
|
||||||
kubelogin --username USERNAME --password PASSWORD
|
|
||||||
|
|
||||||
# Run as a credential plugin.
|
|
||||||
kubelogin get-token --oidc-issuer-url=https://issuer.example.com
|
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
get-token Run as a kubectl credential plugin
|
get-token Run as a kubectl credential plugin
|
||||||
help Help about any command
|
help Help about any command
|
||||||
|
setup Show the setup instruction
|
||||||
version Print the version information
|
version Print the version information
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
--kubeconfig string Path to the kubeconfig file
|
--kubeconfig string Path to the kubeconfig file
|
||||||
--context string The name of the kubeconfig context to use
|
--context string The name of the kubeconfig context to use
|
||||||
--user string The name of the kubeconfig user to use. Prior to --context
|
--user string The name of the kubeconfig user to use. Prior to --context
|
||||||
--certificate-authority string Path to a cert file for the certificate authority
|
|
||||||
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
|
|
||||||
--listen-port ints Port to bind to the local server. If multiple ports are given, it will try the ports in order (default [8000,18000])
|
--listen-port ints Port to bind to the local server. If multiple ports are given, it will try the ports in order (default [8000,18000])
|
||||||
--skip-open-browser If true, it does not open the browser on authentication
|
--skip-open-browser If true, it does not open the browser on authentication
|
||||||
--username string If set, perform the resource owner password credentials grant
|
--username string If set, perform the resource owner password credentials grant
|
||||||
--password string If set, use the password instead of asking it
|
--password string If set, use the password instead of asking it
|
||||||
|
--certificate-authority string Path to a cert file for the certificate authority
|
||||||
|
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
|
||||||
--add_dir_header If true, adds the file directory to the header
|
--add_dir_header If true, adds the file directory to the header
|
||||||
--alsologtostderr log to standard error as well as files
|
--alsologtostderr log to standard error as well as files
|
||||||
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
|
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
|
||||||
@@ -122,8 +120,8 @@ Flags:
|
|||||||
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
|
||||||
-v, --v Level number for the log level verbosity
|
-v, --v Level number for the log level verbosity
|
||||||
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
|
||||||
-h, --help help for kubelogin
|
-h, --help help for main
|
||||||
--version version for kubelogin
|
--version version for main
|
||||||
```
|
```
|
||||||
|
|
||||||
### Kubeconfig
|
### Kubeconfig
|
||||||
|
|||||||
@@ -23,15 +23,6 @@ type Interface interface {
|
|||||||
Run(ctx context.Context, args []string, version string) int
|
Run(ctx context.Context, args []string, version string) int
|
||||||
}
|
}
|
||||||
|
|
||||||
const examples = ` # Login to the provider using the authorization code flow.
|
|
||||||
%[1]s
|
|
||||||
|
|
||||||
# Login to the provider using the resource owner password credentials flow.
|
|
||||||
%[1]s --username USERNAME --password PASSWORD
|
|
||||||
|
|
||||||
# Run as a credential plugin.
|
|
||||||
%[1]s get-token --oidc-issuer-url=https://issuer.example.com`
|
|
||||||
|
|
||||||
var defaultListenPort = []int{8000, 18000}
|
var defaultListenPort = []int{8000, 18000}
|
||||||
var defaultTokenCacheDir = homedir.HomeDir() + "/.kube/cache/oidc-login"
|
var defaultTokenCacheDir = homedir.HomeDir() + "/.kube/cache/oidc-login"
|
||||||
|
|
||||||
|
|||||||
@@ -12,24 +12,29 @@ import (
|
|||||||
|
|
||||||
// getTokenOptions represents the options for get-token command.
|
// getTokenOptions represents the options for get-token command.
|
||||||
type getTokenOptions struct {
|
type getTokenOptions struct {
|
||||||
loginOptions
|
|
||||||
IssuerURL string
|
IssuerURL string
|
||||||
ClientID string
|
ClientID string
|
||||||
ClientSecret string
|
ClientSecret string
|
||||||
ExtraScopes []string
|
ExtraScopes []string
|
||||||
|
ListenPort []int
|
||||||
|
SkipOpenBrowser bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
CertificateAuthority string
|
CertificateAuthority string
|
||||||
SkipTLSVerify bool
|
SkipTLSVerify bool
|
||||||
Verbose int
|
|
||||||
TokenCacheDir string
|
TokenCacheDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *getTokenOptions) register(f *pflag.FlagSet) {
|
func (o *getTokenOptions) register(f *pflag.FlagSet) {
|
||||||
f.SortFlags = false
|
f.SortFlags = false
|
||||||
o.loginOptions.register(f)
|
|
||||||
f.StringVar(&o.IssuerURL, "oidc-issuer-url", "", "Issuer URL of the provider (mandatory)")
|
f.StringVar(&o.IssuerURL, "oidc-issuer-url", "", "Issuer URL of the provider (mandatory)")
|
||||||
f.StringVar(&o.ClientID, "oidc-client-id", "", "Client ID of the provider (mandatory)")
|
f.StringVar(&o.ClientID, "oidc-client-id", "", "Client ID of the provider (mandatory)")
|
||||||
f.StringVar(&o.ClientSecret, "oidc-client-secret", "", "Client secret of the provider")
|
f.StringVar(&o.ClientSecret, "oidc-client-secret", "", "Client secret of the provider")
|
||||||
f.StringSliceVar(&o.ExtraScopes, "oidc-extra-scope", nil, "Scopes to request to the provider")
|
f.StringSliceVar(&o.ExtraScopes, "oidc-extra-scope", nil, "Scopes to request to the provider")
|
||||||
|
f.IntSliceVar(&o.ListenPort, "listen-port", defaultListenPort, "Port to bind to the local server. If multiple ports are given, it will try the ports in order")
|
||||||
|
f.BoolVar(&o.SkipOpenBrowser, "skip-open-browser", false, "If true, it does not open the browser on authentication")
|
||||||
|
f.StringVar(&o.Username, "username", "", "If set, perform the resource owner password credentials grant")
|
||||||
|
f.StringVar(&o.Password, "password", "", "If set, use the password instead of asking it")
|
||||||
f.StringVar(&o.CertificateAuthority, "certificate-authority", "", "Path to a cert file for the certificate authority")
|
f.StringVar(&o.CertificateAuthority, "certificate-authority", "", "Path to a cert file for the certificate authority")
|
||||||
f.BoolVar(&o.SkipTLSVerify, "insecure-skip-tls-verify", false, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
|
f.BoolVar(&o.SkipTLSVerify, "insecure-skip-tls-verify", false, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
|
||||||
f.StringVar(&o.TokenCacheDir, "token-cache-dir", defaultTokenCacheDir, "Path to a directory for caching tokens")
|
f.StringVar(&o.TokenCacheDir, "token-cache-dir", defaultTokenCacheDir, "Path to a directory for caching tokens")
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/int128/kubelogin/pkg/adaptors/kubeconfig"
|
"github.com/int128/kubelogin/pkg/adaptors/kubeconfig"
|
||||||
"github.com/int128/kubelogin/pkg/adaptors/logger"
|
"github.com/int128/kubelogin/pkg/adaptors/logger"
|
||||||
@@ -12,38 +11,40 @@ import (
|
|||||||
"golang.org/x/xerrors"
|
"golang.org/x/xerrors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// kubectlOptions represents kubectl specific options.
|
const longDescription = `Login to the OpenID Connect provider.
|
||||||
type kubectlOptions struct {
|
|
||||||
|
You need to set up the OIDC provider, role binding, Kubernetes API server and kubeconfig.
|
||||||
|
Run the following command to show the setup instruction:
|
||||||
|
|
||||||
|
kubectl oidc-login setup
|
||||||
|
|
||||||
|
See https://github.com/int128/kubelogin for more.
|
||||||
|
`
|
||||||
|
|
||||||
|
// rootOptions represents the options for the root command.
|
||||||
|
type rootOptions struct {
|
||||||
Kubeconfig string
|
Kubeconfig string
|
||||||
Context string
|
Context string
|
||||||
User string
|
User string
|
||||||
|
ListenPort []int
|
||||||
|
SkipOpenBrowser bool
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
CertificateAuthority string
|
CertificateAuthority string
|
||||||
SkipTLSVerify bool
|
SkipTLSVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *kubectlOptions) register(f *pflag.FlagSet) {
|
func (o *rootOptions) register(f *pflag.FlagSet) {
|
||||||
f.SortFlags = false
|
f.SortFlags = false
|
||||||
f.StringVar(&o.Kubeconfig, "kubeconfig", "", "Path to the kubeconfig file")
|
f.StringVar(&o.Kubeconfig, "kubeconfig", "", "Path to the kubeconfig file")
|
||||||
f.StringVar(&o.Context, "context", "", "The name of the kubeconfig context to use")
|
f.StringVar(&o.Context, "context", "", "The name of the kubeconfig context to use")
|
||||||
f.StringVar(&o.User, "user", "", "The name of the kubeconfig user to use. Prior to --context")
|
f.StringVar(&o.User, "user", "", "The name of the kubeconfig user to use. Prior to --context")
|
||||||
f.StringVar(&o.CertificateAuthority, "certificate-authority", "", "Path to a cert file for the certificate authority")
|
|
||||||
f.BoolVar(&o.SkipTLSVerify, "insecure-skip-tls-verify", false, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
|
|
||||||
}
|
|
||||||
|
|
||||||
// loginOptions represents the options for Login use-case.
|
|
||||||
type loginOptions struct {
|
|
||||||
ListenPort []int
|
|
||||||
SkipOpenBrowser bool
|
|
||||||
Username string
|
|
||||||
Password string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o *loginOptions) register(f *pflag.FlagSet) {
|
|
||||||
f.SortFlags = false
|
|
||||||
f.IntSliceVar(&o.ListenPort, "listen-port", defaultListenPort, "Port to bind to the local server. If multiple ports are given, it will try the ports in order")
|
f.IntSliceVar(&o.ListenPort, "listen-port", defaultListenPort, "Port to bind to the local server. If multiple ports are given, it will try the ports in order")
|
||||||
f.BoolVar(&o.SkipOpenBrowser, "skip-open-browser", false, "If true, it does not open the browser on authentication")
|
f.BoolVar(&o.SkipOpenBrowser, "skip-open-browser", false, "If true, it does not open the browser on authentication")
|
||||||
f.StringVar(&o.Username, "username", "", "If set, perform the resource owner password credentials grant")
|
f.StringVar(&o.Username, "username", "", "If set, perform the resource owner password credentials grant")
|
||||||
f.StringVar(&o.Password, "password", "", "If set, use the password instead of asking it")
|
f.StringVar(&o.Password, "password", "", "If set, use the password instead of asking it")
|
||||||
|
f.StringVar(&o.CertificateAuthority, "certificate-authority", "", "Path to a cert file for the certificate authority")
|
||||||
|
f.BoolVar(&o.SkipTLSVerify, "insecure-skip-tls-verify", false, "If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure")
|
||||||
}
|
}
|
||||||
|
|
||||||
type Root struct {
|
type Root struct {
|
||||||
@@ -52,15 +53,12 @@ type Root struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *Root) New(ctx context.Context, executable string) *cobra.Command {
|
func (cmd *Root) New(ctx context.Context, executable string) *cobra.Command {
|
||||||
var o struct {
|
var o rootOptions
|
||||||
kubectlOptions
|
|
||||||
loginOptions
|
|
||||||
}
|
|
||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
Use: executable,
|
Use: executable,
|
||||||
Short: "Login to the OpenID Connect provider and update the kubeconfig",
|
Short: "Login to the OpenID Connect provider",
|
||||||
Example: fmt.Sprintf(examples, executable),
|
Long: longDescription,
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
RunE: func(*cobra.Command, []string) error {
|
RunE: func(*cobra.Command, []string) error {
|
||||||
in := standalone.Input{
|
in := standalone.Input{
|
||||||
KubeconfigFilename: o.Kubeconfig,
|
KubeconfigFilename: o.Kubeconfig,
|
||||||
@@ -79,8 +77,7 @@ func (cmd *Root) New(ctx context.Context, executable string) *cobra.Command {
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
o.kubectlOptions.register(rootCmd.Flags())
|
o.register(rootCmd.Flags())
|
||||||
o.loginOptions.register(rootCmd.Flags())
|
|
||||||
cmd.Logger.AddFlags(rootCmd.PersistentFlags())
|
cmd.Logger.AddFlags(rootCmd.PersistentFlags())
|
||||||
return rootCmd
|
return rootCmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ type DecoderInterface interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DecodedIDToken struct {
|
type DecodedIDToken struct {
|
||||||
IDTokenSubject string
|
Subject string
|
||||||
IDTokenExpiry time.Time
|
Expiry time.Time
|
||||||
IDTokenClaims map[string]string // string representation of claims for logging
|
Claims map[string]string // string representation of claims for logging
|
||||||
}
|
}
|
||||||
|
|
||||||
type Decoder struct{}
|
type Decoder struct{}
|
||||||
@@ -43,9 +43,9 @@ func (d *Decoder) DecodeIDToken(t string) (*DecodedIDToken, error) {
|
|||||||
return nil, xerrors.Errorf("could not decode the json of token: %w", err)
|
return nil, xerrors.Errorf("could not decode the json of token: %w", err)
|
||||||
}
|
}
|
||||||
return &DecodedIDToken{
|
return &DecodedIDToken{
|
||||||
IDTokenSubject: claims.Subject,
|
Subject: claims.Subject,
|
||||||
IDTokenExpiry: time.Unix(claims.ExpiresAt, 0),
|
Expiry: time.Unix(claims.ExpiresAt, 0),
|
||||||
IDTokenClaims: dumpRawClaims(rawClaims),
|
Claims: dumpRawClaims(rawClaims),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ func TestDecoder_DecodeIDToken(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("DecodeIDToken error: %s", err)
|
t.Fatalf("DecodeIDToken error: %s", err)
|
||||||
}
|
}
|
||||||
if decodedToken.IDTokenExpiry != expiry {
|
if decodedToken.Expiry != expiry {
|
||||||
t.Errorf("IDTokenExpiry wants %s but %s", expiry, decodedToken.IDTokenExpiry)
|
t.Errorf("Expiry wants %s but %s", expiry, decodedToken.Expiry)
|
||||||
}
|
}
|
||||||
t.Logf("IDTokenClaims=%+v", decodedToken.IDTokenClaims)
|
t.Logf("Claims=%+v", decodedToken.Claims)
|
||||||
})
|
})
|
||||||
t.Run("InvalidToken", func(t *testing.T) {
|
t.Run("InvalidToken", func(t *testing.T) {
|
||||||
decodedToken, err := decoder.DecodeIDToken("HEADER.INVALID_TOKEN.SIGNATURE")
|
decodedToken, err := decoder.DecodeIDToken("HEADER.INVALID_TOKEN.SIGNATURE")
|
||||||
|
|||||||
@@ -85,18 +85,18 @@ func (u *Authentication) Do(ctx context.Context, in Input) (*Output, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, xerrors.Errorf("invalid token and you need to remove the cache: %w", err)
|
return nil, xerrors.Errorf("invalid token and you need to remove the cache: %w", err)
|
||||||
}
|
}
|
||||||
if token.IDTokenExpiry.After(time.Now()) { //TODO: inject time service
|
if token.Expiry.After(time.Now()) { //TODO: inject time service
|
||||||
u.Logger.V(1).Infof("you already have a valid token until %s", token.IDTokenExpiry)
|
u.Logger.V(1).Infof("you already have a valid token until %s", token.Expiry)
|
||||||
return &Output{
|
return &Output{
|
||||||
AlreadyHasValidIDToken: true,
|
AlreadyHasValidIDToken: true,
|
||||||
IDToken: in.OIDCConfig.IDToken,
|
IDToken: in.OIDCConfig.IDToken,
|
||||||
RefreshToken: in.OIDCConfig.RefreshToken,
|
RefreshToken: in.OIDCConfig.RefreshToken,
|
||||||
IDTokenSubject: token.IDTokenSubject,
|
IDTokenSubject: token.Subject,
|
||||||
IDTokenExpiry: token.IDTokenExpiry,
|
IDTokenExpiry: token.Expiry,
|
||||||
IDTokenClaims: token.IDTokenClaims,
|
IDTokenClaims: token.Claims,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
u.Logger.V(1).Infof("you have an expired token at %s", token.IDTokenExpiry)
|
u.Logger.V(1).Infof("you have an expired token at %s", token.Expiry)
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Logger.V(1).Infof("initializing an OIDCFactory client")
|
u.Logger.V(1).Infof("initializing an OIDCFactory client")
|
||||||
|
|||||||
@@ -274,9 +274,9 @@ func TestAuthentication_Do(t *testing.T) {
|
|||||||
mockOIDCDecoder.EXPECT().
|
mockOIDCDecoder.EXPECT().
|
||||||
DecodeIDToken("VALID_ID_TOKEN").
|
DecodeIDToken("VALID_ID_TOKEN").
|
||||||
Return(&oidc.DecodedIDToken{
|
Return(&oidc.DecodedIDToken{
|
||||||
IDTokenSubject: "YOUR_SUBJECT",
|
Subject: "YOUR_SUBJECT",
|
||||||
IDTokenExpiry: futureTime,
|
Expiry: futureTime,
|
||||||
IDTokenClaims: dummyTokenClaims,
|
Claims: dummyTokenClaims,
|
||||||
}, nil)
|
}, nil)
|
||||||
u := Authentication{
|
u := Authentication{
|
||||||
OIDCFactory: mock_oidc.NewMockFactoryInterface(ctrl),
|
OIDCFactory: mock_oidc.NewMockFactoryInterface(ctrl),
|
||||||
@@ -315,9 +315,9 @@ func TestAuthentication_Do(t *testing.T) {
|
|||||||
mockOIDCDecoder.EXPECT().
|
mockOIDCDecoder.EXPECT().
|
||||||
DecodeIDToken("EXPIRED_ID_TOKEN").
|
DecodeIDToken("EXPIRED_ID_TOKEN").
|
||||||
Return(&oidc.DecodedIDToken{
|
Return(&oidc.DecodedIDToken{
|
||||||
IDTokenSubject: "YOUR_SUBJECT",
|
Subject: "YOUR_SUBJECT",
|
||||||
IDTokenExpiry: pastTime,
|
Expiry: pastTime,
|
||||||
IDTokenClaims: dummyTokenClaims,
|
Claims: dummyTokenClaims,
|
||||||
}, nil)
|
}, nil)
|
||||||
mockOIDCClient := mock_oidc.NewMockInterface(ctrl)
|
mockOIDCClient := mock_oidc.NewMockInterface(ctrl)
|
||||||
mockOIDCClient.EXPECT().
|
mockOIDCClient.EXPECT().
|
||||||
@@ -373,9 +373,9 @@ func TestAuthentication_Do(t *testing.T) {
|
|||||||
mockOIDCDecoder.EXPECT().
|
mockOIDCDecoder.EXPECT().
|
||||||
DecodeIDToken("EXPIRED_ID_TOKEN").
|
DecodeIDToken("EXPIRED_ID_TOKEN").
|
||||||
Return(&oidc.DecodedIDToken{
|
Return(&oidc.DecodedIDToken{
|
||||||
IDTokenSubject: "YOUR_SUBJECT",
|
Subject: "YOUR_SUBJECT",
|
||||||
IDTokenExpiry: pastTime,
|
Expiry: pastTime,
|
||||||
IDTokenClaims: dummyTokenClaims,
|
Claims: dummyTokenClaims,
|
||||||
}, nil)
|
}, nil)
|
||||||
mockOIDCClient := mock_oidc.NewMockInterface(ctrl)
|
mockOIDCClient := mock_oidc.NewMockInterface(ctrl)
|
||||||
mockOIDCClient.EXPECT().
|
mockOIDCClient.EXPECT().
|
||||||
|
|||||||
@@ -37,10 +37,8 @@ type Input struct {
|
|||||||
SkipTLSVerify bool
|
SkipTLSVerify bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const oidcConfigErrorMessage = `NOTE:
|
const oidcConfigErrorMessage = `You need to set up the kubeconfig for OpenID Connect authentication.
|
||||||
You need to setup the kubeconfig for OpenID Connect authentication.
|
|
||||||
See https://github.com/int128/kubelogin for more.
|
See https://github.com/int128/kubelogin for more.
|
||||||
|
|
||||||
`
|
`
|
||||||
|
|
||||||
// Standalone provides the use case of explicit login.
|
// Standalone provides the use case of explicit login.
|
||||||
@@ -99,13 +97,13 @@ func (u *Standalone) Do(ctx context.Context, in Input) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var deprecation = template.Must(template.New("").Parse(
|
var deprecationTpl = template.Must(template.New("").Parse(
|
||||||
`IMPORTANT NOTICE:
|
`IMPORTANT NOTICE:
|
||||||
The credential plugin mode is available since v1.14.0.
|
The credential plugin mode is available since v1.14.0.
|
||||||
Kubectl will automatically run kubelogin and you do not need to run kubelogin explicitly.
|
Kubectl will automatically run kubelogin and you do not need to run kubelogin explicitly.
|
||||||
|
|
||||||
You can switch to the credential plugin mode by setting the following user to
|
You can switch to the credential plugin mode by setting the following user to
|
||||||
{{ .kubeconfig }}.
|
{{ .Kubeconfig }}.
|
||||||
---
|
---
|
||||||
users:
|
users:
|
||||||
- name: oidc
|
- name: oidc
|
||||||
@@ -116,7 +114,7 @@ users:
|
|||||||
args:
|
args:
|
||||||
- oidc-login
|
- oidc-login
|
||||||
- get-token
|
- get-token
|
||||||
{{- range .args }}
|
{{- range .Args }}
|
||||||
- {{ . }}
|
- {{ . }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
---
|
---
|
||||||
@@ -124,6 +122,11 @@ See https://github.com/int128/kubelogin for more.
|
|||||||
|
|
||||||
`))
|
`))
|
||||||
|
|
||||||
|
type deprecationVars struct {
|
||||||
|
Kubeconfig string
|
||||||
|
Args []string
|
||||||
|
}
|
||||||
|
|
||||||
func (u *Standalone) showDeprecation(in Input, p *kubeconfig.AuthProvider) error {
|
func (u *Standalone) showDeprecation(in Input, p *kubeconfig.AuthProvider) error {
|
||||||
var args []string
|
var args []string
|
||||||
args = append(args, "--oidc-issuer-url="+p.OIDCConfig.IDPIssuerURL)
|
args = append(args, "--oidc-issuer-url="+p.OIDCConfig.IDPIssuerURL)
|
||||||
@@ -144,12 +147,12 @@ func (u *Standalone) showDeprecation(in Input, p *kubeconfig.AuthProvider) error
|
|||||||
args = append(args, "--username="+in.Username)
|
args = append(args, "--username="+in.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
m := map[string]interface{}{
|
v := deprecationVars{
|
||||||
"kubeconfig": p.LocationOfOrigin,
|
Kubeconfig: p.LocationOfOrigin,
|
||||||
"args": args,
|
Args: args,
|
||||||
}
|
}
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
if err := deprecation.ExecuteTemplate(&b, "", m); err != nil {
|
if err := deprecationTpl.Execute(&b, &v); err != nil {
|
||||||
return xerrors.Errorf("could not render the template: %w", err)
|
return xerrors.Errorf("could not render the template: %w", err)
|
||||||
}
|
}
|
||||||
u.Logger.Printf("%s", b.String())
|
u.Logger.Printf("%s", b.String())
|
||||||
|
|||||||
Reference in New Issue
Block a user