Skip to content

Commit bc7e71f

Browse files
authored
Change default token cache storage to disk (#1264)
* Change default token cache storage to disk * Fix * Fix * Clean up both storages
1 parent 19d61e7 commit bc7e71f

File tree

13 files changed

+60
-103
lines changed

13 files changed

+60
-103
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,16 +83,16 @@ If the refresh token has expired, it will perform re-authentication.
8383

8484
### Token cache
8585

86-
If the OS keyring is available, kubelogin stores the token cache to the OS keyring.
87-
Otherwise, kubelogin stores the token cache to the file system.
86+
Kubelogin stores the token cache to the file system by default.
87+
For enhanced security, it is recommended to store it to the keyring.
8888
See the [token cache](docs/usage.md#token-cache) for details.
8989

9090
You can log out by deleting the token cache.
9191

9292
```console
9393
% kubectl oidc-login clean
9494
Deleted the token cache at /home/user/.kube/cache/oidc-login
95-
Deleted the token cache in the keyring
95+
Deleted the token cache from the keyring
9696
```
9797

9898
Kubelogin will ask you to log in via the browser again.

docs/setup.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ Add `oidc` user to the kubeconfig.
203203

204204
```sh
205205
kubectl config set-credentials oidc \
206-
--exec-interactive-mode=Never
206+
--exec-interactive-mode=Never \
207207
--exec-api-version=client.authentication.k8s.io/v1 \
208208
--exec-command=kubectl \
209209
--exec-arg=oidc-login \
@@ -214,6 +214,9 @@ kubectl config set-credentials oidc \
214214

215215
If your provider requires a client secret, add `--oidc-client-secret=YOUR_CLIENT_SECRET`.
216216

217+
For security, it is recommended to add `--token-cache-storage=keyring` to store the token cache to the keyring instead of the file system.
218+
If you encounter an error, see the [token cache](usage.md#token-cache) for details.
219+
217220
## 6. Verify cluster access
218221

219222
Make sure you can access the Kubernetes cluster.

docs/usage.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ Flags:
1414
--oidc-use-access-token Instead of using the id_token, use the access_token to authenticate to Kubernetes
1515
--force-refresh If set, refresh the ID token regardless of its expiration time
1616
--token-cache-dir string Path to a directory of the token cache (default "~/.kube/cache/oidc-login")
17-
--token-cache-storage string Storage for the token cache. One of (auto|keyring|disk) (default "auto")
17+
--token-cache-storage string Storage for the token cache. One of (disk|keyring) (default "disk")
1818
--certificate-authority stringArray Path to a cert file for the certificate authority
1919
--certificate-authority-data stringArray Base64 encoded cert for the certificate authority
2020
--insecure-skip-tls-verify [SECURITY RISK] If set, the server's certificate will not be checked for validity
@@ -105,16 +105,21 @@ See also [net/http#ProxyFromEnvironment](https://golang.org/pkg/net/http/#ProxyF
105105

106106
### Token cache
107107

108-
Kubelogin stores the token cache to the OS keyring if available.
109-
It depends on [zalando/go-keyring](https://github.com/zalando/go-keyring) for the keyring storage.
108+
Kubelogin stores the token cache to the file system by default.
110109

111-
If you encounter a problem, try `--token-cache-storage` to set the storage.
110+
You can store the token cache to the OS keyring for enhanced security.
111+
It depends on [zalando/go-keyring](https://github.com/zalando/go-keyring).
112112

113113
```yaml
114-
# Force to use the OS keyring
115114
- --token-cache-storage=keyring
116-
# Force to use the file system
117-
- --token-cache-storage=disk
115+
```
116+
117+
You can delete the token cache by the clean command.
118+
119+
```console
120+
% kubectl oidc-login clean
121+
Deleted the token cache at /home/user/.kube/cache/oidc-login
122+
Deleted the token cache from the keyring
118123
```
119124

120125
### Home directory expansion

integration_test/clean_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ func TestClean(t *testing.T) {
2020
"kubelogin",
2121
"clean",
2222
"--token-cache-dir", tokenCacheDir,
23-
"--token-cache-storage", "disk",
2423
}, "HEAD")
2524
if exitCode != 0 {
2625
t.Errorf("exit status wants 0 but %d", exitCode)

integration_test/credetial_plugin_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,6 @@ func runGetToken(t *testing.T, ctx context.Context, cfg getTokenConfig) {
443443
"kubelogin",
444444
"get-token",
445445
"--token-cache-dir", cfg.tokenCacheDir,
446-
"--token-cache-storage", "disk",
447446
"--oidc-issuer-url", cfg.issuerURL,
448447
"--oidc-client-id", "kubernetes",
449448
"--listen-address", "127.0.0.1:0",

pkg/cmd/clean.go

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,11 @@ import (
99
)
1010

1111
type cleanOptions struct {
12-
tokenCacheOptions tokenCacheOptions
12+
TokenCacheDir string
1313
}
1414

1515
func (o *cleanOptions) addFlags(f *pflag.FlagSet) {
16-
o.tokenCacheOptions.addFlags(f)
17-
}
18-
19-
func (o *cleanOptions) expandHomedir() {
20-
o.tokenCacheOptions.expandHomedir()
16+
f.StringVar(&o.TokenCacheDir, "token-cache-dir", getDefaultTokenCacheDir(), "Path to a directory of the token cache")
2117
}
2218

2319
type Clean struct {
@@ -31,18 +27,13 @@ func (cmd *Clean) New() *cobra.Command {
3127
Short: "Delete the token cache",
3228
Long: `Delete the token cache.
3329
34-
This deletes both the OS keyring and the directory by default.
35-
If you encounter an error of keyring, try --token-cache-storage=disk.
30+
This deletes the token cache directory from both the file system and the keyring.
3631
`,
3732
Args: cobra.NoArgs,
3833
RunE: func(c *cobra.Command, _ []string) error {
39-
o.expandHomedir()
40-
tokenCacheConfig, err := o.tokenCacheOptions.tokenCacheConfig()
41-
if err != nil {
42-
return fmt.Errorf("clean: %w", err)
43-
}
34+
o.TokenCacheDir = expandHomedir(o.TokenCacheDir)
4435
in := clean.Input{
45-
TokenCacheConfig: tokenCacheConfig,
36+
TokenCacheDir: o.TokenCacheDir,
4637
}
4738
if err := cmd.Clean.Do(c.Context(), in); err != nil {
4839
return fmt.Errorf("clean: %w", err)

pkg/cmd/cmd_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ func TestCmd_Run(t *testing.T) {
118118
},
119119
TokenCacheConfig: tokencache.Config{
120120
Directory: filepath.Join(userHomeDir, ".kube/cache/oidc-login"),
121-
Storage: tokencache.StorageAuto,
122121
},
123122
GrantOptionSet: defaultGrantOptionSet,
124123
},
@@ -131,7 +130,7 @@ func TestCmd_Run(t *testing.T) {
131130
"--oidc-client-secret", "YOUR_CLIENT_SECRET",
132131
"--oidc-extra-scope", "email",
133132
"--oidc-extra-scope", "profile",
134-
"--token-cache-storage", "disk",
133+
"--token-cache-storage", "keyring",
135134
"-v1",
136135
},
137136
in: credentialplugin.Input{
@@ -143,7 +142,7 @@ func TestCmd_Run(t *testing.T) {
143142
},
144143
TokenCacheConfig: tokencache.Config{
145144
Directory: filepath.Join(userHomeDir, ".kube/cache/oidc-login"),
146-
Storage: tokencache.StorageDisk,
145+
Storage: tokencache.StorageKeyring,
147146
},
148147
GrantOptionSet: defaultGrantOptionSet,
149148
},
@@ -163,7 +162,6 @@ func TestCmd_Run(t *testing.T) {
163162
},
164163
TokenCacheConfig: tokencache.Config{
165164
Directory: filepath.Join(userHomeDir, ".kube/cache/oidc-login"),
166-
Storage: tokencache.StorageAuto,
167165
},
168166
GrantOptionSet: defaultGrantOptionSet,
169167
},
@@ -185,7 +183,6 @@ func TestCmd_Run(t *testing.T) {
185183
},
186184
TokenCacheConfig: tokencache.Config{
187185
Directory: filepath.Join(userHomeDir, ".kube/oidc-cache"),
188-
Storage: tokencache.StorageAuto,
189186
},
190187
GrantOptionSet: authentication.GrantOptionSet{
191188
AuthCodeBrowserOption: &authcode.BrowserOption{

pkg/cmd/tokencache.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func getDefaultTokenCacheDir() string {
1818
return filepath.Join("~", ".kube", "cache", "oidc-login")
1919
}
2020

21-
var allTokenCacheStorage = strings.Join([]string{"auto", "keyring", "disk"}, "|")
21+
var allTokenCacheStorage = strings.Join([]string{"disk", "keyring"}, "|")
2222

2323
type tokenCacheOptions struct {
2424
TokenCacheDir string
@@ -27,7 +27,7 @@ type tokenCacheOptions struct {
2727

2828
func (o *tokenCacheOptions) addFlags(f *pflag.FlagSet) {
2929
f.StringVar(&o.TokenCacheDir, "token-cache-dir", getDefaultTokenCacheDir(), "Path to a directory of the token cache")
30-
f.StringVar(&o.TokenCacheStorage, "token-cache-storage", "auto", fmt.Sprintf("Storage for the token cache. One of (%s)", allTokenCacheStorage))
30+
f.StringVar(&o.TokenCacheStorage, "token-cache-storage", "disk", fmt.Sprintf("Storage for the token cache. One of (%s)", allTokenCacheStorage))
3131
}
3232

3333
func (o *tokenCacheOptions) expandHomedir() {
@@ -39,12 +39,10 @@ func (o *tokenCacheOptions) tokenCacheConfig() (tokencache.Config, error) {
3939
Directory: o.TokenCacheDir,
4040
}
4141
switch o.TokenCacheStorage {
42-
case "auto":
43-
config.Storage = tokencache.StorageAuto
44-
case "keyring":
45-
config.Storage = tokencache.StorageKeyring
4642
case "disk":
4743
config.Storage = tokencache.StorageDisk
44+
case "keyring":
45+
config.Storage = tokencache.StorageKeyring
4846
default:
4947
return tokencache.Config{}, fmt.Errorf("token-cache-storage must be one of (%s)", allTokenCacheStorage)
5048
}

pkg/di/wire_gen.go

Lines changed: 1 addition & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/tokencache/repository/repository.go

Lines changed: 15 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,13 @@ import (
55
"encoding/gob"
66
"encoding/hex"
77
"encoding/json"
8-
"errors"
98
"fmt"
109
"io"
1110
"os"
1211
"path/filepath"
1312

1413
"github.com/gofrs/flock"
1514
"github.com/google/wire"
16-
"github.com/int128/kubelogin/pkg/infrastructure/logger"
1715
"github.com/int128/kubelogin/pkg/oidc"
1816
"github.com/int128/kubelogin/pkg/tokencache"
1917
"github.com/zalando/go-keyring"
@@ -39,9 +37,7 @@ type entity struct {
3937

4038
// Repository provides access to the token cache on the local filesystem.
4139
// Filename of a token cache is sha256 digest of the issuer, zero-character and client ID.
42-
type Repository struct {
43-
Logger logger.Interface
44-
}
40+
type Repository struct{}
4541

4642
// keyringService is used to namespace the keyring access.
4743
// Some implementations may also display this string when prompting the user
@@ -57,16 +53,6 @@ func (r *Repository) FindByKey(config tokencache.Config, key tokencache.Key) (*o
5753
return nil, fmt.Errorf("could not compute the key: %w", err)
5854
}
5955
switch config.Storage {
60-
case tokencache.StorageAuto:
61-
t, err := readFromKeyring(checksum)
62-
if errors.Is(err, keyring.ErrUnsupportedPlatform) ||
63-
errors.Is(err, keyring.ErrNotFound) {
64-
return readFromFile(config, checksum)
65-
}
66-
if err != nil {
67-
return nil, err
68-
}
69-
return t, nil
7056
case tokencache.StorageDisk:
7157
return readFromFile(config, checksum)
7258
case tokencache.StorageKeyring:
@@ -120,17 +106,6 @@ func (r *Repository) Save(config tokencache.Config, key tokencache.Key, tokenSet
120106
return fmt.Errorf("could not compute the key: %w", err)
121107
}
122108
switch config.Storage {
123-
case tokencache.StorageAuto:
124-
if err := writeToKeyring(checksum, tokenSet); err != nil {
125-
if errors.Is(err, keyring.ErrUnsupportedPlatform) {
126-
return writeToFile(config, checksum, tokenSet)
127-
}
128-
if errors.Is(err, keyring.ErrSetDataTooBig) {
129-
return writeToFile(config, checksum, tokenSet)
130-
}
131-
return err
132-
}
133-
return nil
134109
case tokencache.StorageDisk:
135110
return writeToFile(config, checksum, tokenSet)
136111
case tokencache.StorageKeyring:
@@ -188,36 +163,20 @@ func (r *Repository) Lock(config tokencache.Config, key tokencache.Key) (io.Clos
188163
}
189164

190165
func (r *Repository) DeleteAll(config tokencache.Config) error {
191-
return errors.Join(
192-
func() error {
193-
if err := os.RemoveAll(config.Directory); err != nil {
194-
return fmt.Errorf("remove the directory %s: %w", config.Directory, err)
195-
}
196-
r.Logger.Printf("Deleted the token cache at %s", config.Directory)
197-
return nil
198-
}(),
199-
func() error {
200-
switch config.Storage {
201-
case tokencache.StorageAuto:
202-
if err := keyring.DeleteAll(keyringService); err != nil {
203-
if errors.Is(err, keyring.ErrUnsupportedPlatform) {
204-
return nil
205-
}
206-
return fmt.Errorf("keyring delete: %w", err)
207-
}
208-
r.Logger.Printf("Deleted the token cache in the keyring")
209-
return nil
210-
case tokencache.StorageKeyring:
211-
if err := keyring.DeleteAll(keyringService); err != nil {
212-
return fmt.Errorf("keyring delete: %w", err)
213-
}
214-
r.Logger.Printf("Deleted the token cache in the keyring")
215-
return nil
216-
default:
217-
return nil
218-
}
219-
}(),
220-
)
166+
switch config.Storage {
167+
case tokencache.StorageDisk:
168+
if err := os.RemoveAll(config.Directory); err != nil {
169+
return fmt.Errorf("remove the directory %s: %w", config.Directory, err)
170+
}
171+
return nil
172+
case tokencache.StorageKeyring:
173+
if err := keyring.DeleteAll(keyringService); err != nil {
174+
return fmt.Errorf("keyring delete: %w", err)
175+
}
176+
return nil
177+
default:
178+
return fmt.Errorf("unknown storage mode: %v", config.Storage)
179+
}
221180
}
222181

223182
func encodeKey(tokenSet oidc.TokenSet) ([]byte, error) {

pkg/tokencache/types.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,8 @@ type Config struct {
2525
type Storage byte
2626

2727
const (
28-
// StorageAuto will prefer keyring when available, and fallback to disk when not.
29-
StorageAuto Storage = iota
3028
// StorageDisk will only store cached keys on disk.
31-
StorageDisk
29+
StorageDisk Storage = iota
3230
// StorageDisk will only store cached keys in the OS keyring.
3331
StorageKeyring
3432
)

pkg/usecases/clean/clean.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type Interface interface {
2121

2222
// Input represents an input of the Clean use-case.
2323
type Input struct {
24-
TokenCacheConfig tokencache.Config
24+
TokenCacheDir string
2525
}
2626

2727
type Clean struct {
@@ -31,8 +31,17 @@ type Clean struct {
3131

3232
func (u *Clean) Do(ctx context.Context, in Input) error {
3333
u.Logger.V(1).Infof("Deleting the token cache")
34-
if err := u.TokenCacheRepository.DeleteAll(in.TokenCacheConfig); err != nil {
35-
return fmt.Errorf("delete the token cache: %w", err)
34+
35+
if err := u.TokenCacheRepository.DeleteAll(tokencache.Config{Directory: in.TokenCacheDir, Storage: tokencache.StorageDisk}); err != nil {
36+
return fmt.Errorf("delete the token cache from %s: %w", in.TokenCacheDir, err)
37+
}
38+
u.Logger.Printf("Deleted the token cache from %s", in.TokenCacheDir)
39+
40+
if err := u.TokenCacheRepository.DeleteAll(tokencache.Config{Directory: in.TokenCacheDir, Storage: tokencache.StorageKeyring}); err != nil {
41+
// Do not return an error because the keyring may not be available.
42+
u.Logger.Printf("Could not delete the token cache from the keyring: %s", err)
43+
} else {
44+
u.Logger.Printf("Deleted the token cache from the keyring")
3645
}
3746
return nil
3847
}

system_test/login/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ test: build
2929
--exec-arg=--oidc-client-id=YOUR_CLIENT_ID \
3030
--exec-arg=--oidc-client-secret=YOUR_CLIENT_SECRET \
3131
--exec-arg=--oidc-extra-scope=email \
32+
--exec-arg=--token-cache-storage=keyring \
3233
--exec-arg=--certificate-authority=$(CERT_DIR)/ca.crt \
3334
--exec-arg=--browser-command=$(BIN_DIR)/chromelogin
3435

0 commit comments

Comments
 (0)