Skip to content

Commit 7157dad

Browse files
ske kubeconfig login: encrypt cache
1 parent 4074118 commit 7157dad

File tree

3 files changed

+80
-10
lines changed

3 files changed

+80
-10
lines changed

internal/pkg/auth/storage.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const (
3737
PRIVATE_KEY authFieldKey = "private_key"
3838
TOKEN_CUSTOM_ENDPOINT authFieldKey = "token_custom_endpoint"
3939
IDP_TOKEN_ENDPOINT authFieldKey = "idp_token_endpoint" //nolint:gosec // linter false positive
40+
CACHE_ENCRYPTION_KEY authFieldKey = "cache_encryption_key"
4041
)
4142

4243
const (
@@ -59,6 +60,7 @@ var authFieldKeys = []authFieldKey{
5960
TOKEN_CUSTOM_ENDPOINT,
6061
IDP_TOKEN_ENDPOINT,
6162
authFlowType,
63+
CACHE_ENCRYPTION_KEY,
6264
}
6365

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

internal/pkg/cache/cache.go

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
package cache
22

33
import (
4+
"crypto/aes"
5+
"crypto/cipher"
6+
"crypto/rand"
7+
"encoding/base64"
48
"errors"
59
"fmt"
610
"os"
711
"path/filepath"
812
"regexp"
13+
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/auth"
915
)
1016

1117
var (
12-
cacheFolderPath string
18+
cacheFolderPath string
19+
cacheEncryptionKey []byte
1320

1421
identifierRegex = regexp.MustCompile("^[a-zA-Z0-9-]+$")
1522
ErrorInvalidCacheIdentifier = fmt.Errorf("invalid cache identifier")
@@ -21,6 +28,25 @@ func Init() error {
2128
return fmt.Errorf("get user cache dir: %w", err)
2229
}
2330
cacheFolderPath = filepath.Join(cacheDir, "stackit")
31+
32+
key, _ := auth.GetAuthField(auth.CACHE_ENCRYPTION_KEY)
33+
cacheEncryptionKey = nil
34+
if key != "" {
35+
cacheEncryptionKey, _ = base64.StdEncoding.DecodeString(key)
36+
// invalid key length
37+
if len(cacheEncryptionKey) != 32 {
38+
cacheEncryptionKey = nil
39+
}
40+
}
41+
if len(cacheEncryptionKey) == 0 {
42+
cacheEncryptionKey = make([]byte, 32)
43+
_, err := rand.Read(cacheEncryptionKey)
44+
if err != nil {
45+
return fmt.Errorf("cache encryption key: %v", err)
46+
}
47+
key := base64.StdEncoding.EncodeToString(cacheEncryptionKey)
48+
return auth.SetAuthField(auth.CACHE_ENCRYPTION_KEY, key)
49+
}
2450
return nil
2551
}
2652

@@ -32,7 +58,21 @@ func GetObject(identifier string) ([]byte, error) {
3258
return nil, ErrorInvalidCacheIdentifier
3359
}
3460

35-
return os.ReadFile(filepath.Join(cacheFolderPath, identifier))
61+
data, err := os.ReadFile(filepath.Join(cacheFolderPath, identifier))
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
block, err := aes.NewCipher(cacheEncryptionKey)
67+
if err != nil {
68+
return nil, err
69+
}
70+
aead, err := cipher.NewGCMWithRandomNonce(block)
71+
if err != nil {
72+
return nil, err
73+
}
74+
75+
return aead.Open(nil, nil, data, nil)
3676
}
3777

3878
func PutObject(identifier string, data []byte) error {
@@ -48,7 +88,17 @@ func PutObject(identifier string, data []byte) error {
4888
return err
4989
}
5090

51-
return os.WriteFile(filepath.Join(cacheFolderPath, identifier), data, 0o600)
91+
block, err := aes.NewCipher(cacheEncryptionKey)
92+
if err != nil {
93+
return err
94+
}
95+
aead, err := cipher.NewGCMWithRandomNonce(block)
96+
if err != nil {
97+
return err
98+
}
99+
encrypted := aead.Seal(nil, nil, data, nil)
100+
101+
return os.WriteFile(filepath.Join(cacheFolderPath, identifier), encrypted, 0o600)
52102
}
53103

54104
func DeleteObject(identifier string) error {

internal/pkg/cache/cache_test.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ import (
66
"path/filepath"
77
"testing"
88

9+
"github.com/google/go-cmp/cmp"
910
"github.com/google/uuid"
1011
)
1112

12-
func TestGetObject(t *testing.T) {
13+
func TestGetObjectErrors(t *testing.T) {
1314
if err := Init(); err != nil {
1415
t.Fatalf("cache init failed: %s", err)
1516
}
@@ -20,12 +21,6 @@ func TestGetObject(t *testing.T) {
2021
expectFile bool
2122
expectedErr error
2223
}{
23-
{
24-
description: "identifier exists",
25-
identifier: "test-cache-get-exists",
26-
expectFile: true,
27-
expectedErr: nil,
28-
},
2924
{
3025
description: "identifier does not exist",
3126
identifier: "test-cache-get-not-exists",
@@ -205,3 +200,26 @@ func TestDeleteObject(t *testing.T) {
205200
})
206201
}
207202
}
203+
204+
func TestWriteAndRead(t *testing.T) {
205+
if err := Init(); err != nil {
206+
t.Fatalf("cache init failed: %s", err)
207+
}
208+
209+
id := "test-cycle-" + uuid.NewString()
210+
data := []byte("test-data")
211+
err := PutObject(id, data)
212+
if err != nil {
213+
t.Fatalf("putobject failed: %v", err)
214+
}
215+
216+
readData, err := GetObject(id)
217+
if err != nil {
218+
t.Fatalf("getobject failed: %v", err)
219+
}
220+
221+
diff := cmp.Diff(data, readData)
222+
if diff != "" {
223+
t.Fatalf("unexpected data diff: %v", diff)
224+
}
225+
}

0 commit comments

Comments
 (0)