Skip to content

Commit 0b3de39

Browse files
ske kubeconfig login: regularly rotate cache encryption key
1 parent 7157dad commit 0b3de39

File tree

2 files changed

+38
-13
lines changed

2 files changed

+38
-13
lines changed

internal/pkg/auth/storage.go

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,18 @@ const (
2727
)
2828

2929
const (
30-
SESSION_EXPIRES_AT_UNIX authFieldKey = "session_expires_at_unix"
31-
ACCESS_TOKEN authFieldKey = "access_token"
32-
REFRESH_TOKEN authFieldKey = "refresh_token"
33-
SERVICE_ACCOUNT_TOKEN authFieldKey = "service_account_token"
34-
SERVICE_ACCOUNT_EMAIL authFieldKey = "service_account_email"
35-
USER_EMAIL authFieldKey = "user_email"
36-
SERVICE_ACCOUNT_KEY authFieldKey = "service_account_key"
37-
PRIVATE_KEY authFieldKey = "private_key"
38-
TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint"
39-
IDP_TOKEN_ENDPOINT authFieldKey = "idp_token_endpoint" //nolint:gosec // linter false positive
40-
CACHE_ENCRYPTION_KEY authFieldKey = "cache_encryption_key"
30+
SESSION_EXPIRES_AT_UNIX authFieldKey = "session_expires_at_unix"
31+
ACCESS_TOKEN authFieldKey = "access_token"
32+
REFRESH_TOKEN authFieldKey = "refresh_token"
33+
SERVICE_ACCOUNT_TOKEN authFieldKey = "service_account_token"
34+
SERVICE_ACCOUNT_EMAIL authFieldKey = "service_account_email"
35+
USER_EMAIL authFieldKey = "user_email"
36+
SERVICE_ACCOUNT_KEY authFieldKey = "service_account_key"
37+
PRIVATE_KEY authFieldKey = "private_key"
38+
TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint"
39+
IDP_TOKEN_ENDPOINT authFieldKey = "idp_token_endpoint" //nolint:gosec // linter false positive
40+
CACHE_ENCRYPTION_KEY authFieldKey = "cache_encryption_key"
41+
CACHE_ENCRYPTION_KEY_AGE authFieldKey = "cache_encryption_key_age"
4142
)
4243

4344
const (
@@ -61,6 +62,7 @@ var authFieldKeys = []authFieldKey{
6162
IDP_TOKEN_ENDPOINT,
6263
authFlowType,
6364
CACHE_ENCRYPTION_KEY,
65+
CACHE_ENCRYPTION_KEY_AGE,
6466
}
6567

6668
// All fields that are set when a user logs in

internal/pkg/cache/cache.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"os"
1111
"path/filepath"
1212
"regexp"
13+
"strconv"
14+
"time"
1315

1416
"github.com/stackitcloud/stackit-cli/internal/pkg/auth"
1517
)
@@ -22,16 +24,30 @@ var (
2224
ErrorInvalidCacheIdentifier = fmt.Errorf("invalid cache identifier")
2325
)
2426

27+
const (
28+
cacheKeyMaxAge = 90 * 24 * time.Hour
29+
)
30+
2531
func Init() error {
2632
cacheDir, err := os.UserCacheDir()
2733
if err != nil {
2834
return fmt.Errorf("get user cache dir: %w", err)
2935
}
3036
cacheFolderPath = filepath.Join(cacheDir, "stackit")
3137

38+
// Encryption keys should only be used a limited number of times for aes-gcm.
39+
// Thus, refresh the key periodically. This will invalidate all cached entries.
3240
key, _ := auth.GetAuthField(auth.CACHE_ENCRYPTION_KEY)
41+
age, _ := auth.GetAuthField(auth.CACHE_ENCRYPTION_KEY_AGE)
3342
cacheEncryptionKey = nil
34-
if key != "" {
43+
var keyAge time.Time
44+
if age != "" {
45+
ageSeconds, err := strconv.ParseInt(age, 10, 64)
46+
if err == nil {
47+
keyAge = time.Unix(ageSeconds, 0)
48+
}
49+
}
50+
if key != "" && keyAge.Add(cacheKeyMaxAge).After(time.Now()) {
3551
cacheEncryptionKey, _ = base64.StdEncoding.DecodeString(key)
3652
// invalid key length
3753
if len(cacheEncryptionKey) != 32 {
@@ -45,7 +61,14 @@ func Init() error {
4561
return fmt.Errorf("cache encryption key: %v", err)
4662
}
4763
key := base64.StdEncoding.EncodeToString(cacheEncryptionKey)
48-
return auth.SetAuthField(auth.CACHE_ENCRYPTION_KEY, key)
64+
err = auth.SetAuthField(auth.CACHE_ENCRYPTION_KEY, key)
65+
if err != nil {
66+
return fmt.Errorf("save cache encryption key: %v", err)
67+
}
68+
err = auth.SetAuthField(auth.CACHE_ENCRYPTION_KEY_AGE, fmt.Sprint(time.Now().Unix()))
69+
if err != nil {
70+
return fmt.Errorf("save cache encryption key age: %v", err)
71+
}
4972
}
5073
return nil
5174
}

0 commit comments

Comments
 (0)