Skip to content

Commit d1fe8d4

Browse files
committed
delete profile removes keyring entries
1 parent 82be06c commit d1fe8d4

File tree

3 files changed

+211
-9
lines changed

3 files changed

+211
-9
lines changed

internal/cmd/config/profile/delete/delete.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/stackitcloud/stackit-cli/internal/pkg/args"
7+
"github.com/stackitcloud/stackit-cli/internal/pkg/auth"
78
"github.com/stackitcloud/stackit-cli/internal/pkg/config"
89
"github.com/stackitcloud/stackit-cli/internal/pkg/errors"
910
"github.com/stackitcloud/stackit-cli/internal/pkg/examples"
@@ -63,6 +64,11 @@ func NewCmd(p *print.Printer) *cobra.Command {
6364
return fmt.Errorf("delete profile: %w", err)
6465
}
6566

67+
err = auth.DeleteProfileFromKeyring(model.Profile)
68+
if err != nil {
69+
return fmt.Errorf("delete profile from keyring: %w", err)
70+
}
71+
6672
p.Info("Successfully deleted profile %q\n", model.Profile)
6773

6874
return nil

internal/pkg/auth/storage.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,23 @@ const (
4444
AUTH_FLOW_SERVICE_ACCOUNT_KEY AuthFlow = "sa_key"
4545
)
4646

47+
// Returns all auth field keys managed by the auth storage
48+
func getAllAuthFieldKeys() []authFieldKey {
49+
return []authFieldKey{
50+
SESSION_EXPIRES_AT_UNIX,
51+
ACCESS_TOKEN,
52+
REFRESH_TOKEN,
53+
SERVICE_ACCOUNT_TOKEN,
54+
SERVICE_ACCOUNT_EMAIL,
55+
USER_EMAIL,
56+
SERVICE_ACCOUNT_KEY,
57+
PRIVATE_KEY,
58+
TOKEN_CUSTOM_ENDPOINT,
59+
JWKS_CUSTOM_ENDPOINT,
60+
authFlowType,
61+
}
62+
}
63+
4764
func SetAuthFlow(value AuthFlow) error {
4865
return SetAuthField(authFlowType, string(value))
4966
}
@@ -87,6 +104,15 @@ func setAuthFieldInKeyring(activeProfile string, key authFieldKey, value string)
87104
return keyring.Set(keyringService, string(key), value)
88105
}
89106

107+
func deleteAuthFieldInKeyring(activeProfile string, key authFieldKey) error {
108+
keyringServiceLocal := keyringService
109+
if activeProfile != config.DefaultProfileName {
110+
keyringServiceLocal = filepath.Join(keyringService, activeProfile)
111+
}
112+
113+
return keyring.Delete(keyringServiceLocal, string(key))
114+
}
115+
90116
func setAuthFieldInEncodedTextFile(activeProfile string, key authFieldKey, value string) error {
91117
err := createEncodedTextFile(activeProfile)
92118
if err != nil {
@@ -245,3 +271,22 @@ func GetProfileEmail(profile string) string {
245271
}
246272
return email
247273
}
274+
275+
func DeleteProfileFromKeyring(profile string) error {
276+
allKeys := getAllAuthFieldKeys()
277+
278+
err := config.ValidateProfile(profile)
279+
if err != nil {
280+
return fmt.Errorf("validate profile: %w", err)
281+
}
282+
283+
for _, key := range allKeys {
284+
err := deleteAuthFieldInKeyring(profile, key)
285+
if err != nil {
286+
// If the key doesn't exist, continue
287+
continue
288+
}
289+
}
290+
291+
return nil
292+
}

internal/pkg/auth/storage_test.go

Lines changed: 160 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,166 @@ func TestSetGetAuthFieldKeyring(t *testing.T) {
468468
}
469469
}
470470

471+
func TestDeleteAuthFieldKeyring(t *testing.T) {
472+
tests := []struct {
473+
description string
474+
activeProfile string
475+
noKey bool
476+
isValid bool
477+
}{
478+
{
479+
description: "base, default profile",
480+
activeProfile: config.DefaultProfileName,
481+
isValid: true,
482+
},
483+
{
484+
description: "key doesnt exist, default profile",
485+
activeProfile: config.DefaultProfileName,
486+
noKey: true,
487+
isValid: false,
488+
},
489+
{
490+
description: "base, custom profile",
491+
activeProfile: "test-profile",
492+
isValid: true,
493+
},
494+
{
495+
description: "key doesnt exist, custom profile",
496+
activeProfile: "test-profile",
497+
noKey: true,
498+
isValid: false,
499+
},
500+
}
501+
502+
for _, tt := range tests {
503+
t.Run(tt.description, func(t *testing.T) {
504+
keyring.MockInit()
505+
506+
// Append random string to auth field key and value to avoid conflicts
507+
testField1 := authFieldKey(fmt.Sprintf("test-field-1-%s", time.Now().Format(time.RFC3339)))
508+
testValue1 := fmt.Sprintf("value-1-keyring-%s", time.Now().Format(time.RFC3339))
509+
510+
// Append random string to profile name to avoid conflicts
511+
tt.activeProfile = makeProfileNameUnique(tt.activeProfile)
512+
513+
// Make sure profile name is valid
514+
err := config.ValidateProfile(tt.activeProfile)
515+
if err != nil {
516+
t.Fatalf("Profile name \"%s\" is invalid: %v", tt.activeProfile, err)
517+
}
518+
519+
if !tt.noKey {
520+
err := setAuthFieldInKeyring(tt.activeProfile, testField1, testValue1)
521+
if err != nil {
522+
t.Fatalf("Failed to set \"%s\" as \"%s\": %v", testField1, testValue1, err)
523+
}
524+
}
525+
526+
err = deleteAuthFieldInKeyring(tt.activeProfile, testField1)
527+
if err != nil {
528+
if tt.isValid {
529+
t.Fatalf("Failed to delete field \"%s\" from keyring: %v", testField1, err)
530+
}
531+
return
532+
}
533+
534+
if !tt.isValid {
535+
t.Fatalf("Expected error when deleting field \"%s\" from keyring, got none", testField1)
536+
}
537+
538+
// Check if key still exists
539+
_, err = getAuthFieldFromKeyring(tt.activeProfile, testField1)
540+
if err == nil {
541+
t.Fatalf("Key \"%s\" still exists in keyring after deletion", testField1)
542+
}
543+
})
544+
}
545+
}
546+
547+
func TestDeleteProfileFromKeyring(t *testing.T) {
548+
tests := []struct {
549+
description string
550+
keys []authFieldKey
551+
activeProfile string
552+
isValid bool
553+
}{
554+
{
555+
description: "base, default profile",
556+
keys: getAllAuthFieldKeys(),
557+
activeProfile: config.DefaultProfileName,
558+
isValid: true,
559+
},
560+
{
561+
description: "missing keys, default profile",
562+
keys: []authFieldKey{
563+
ACCESS_TOKEN,
564+
SERVICE_ACCOUNT_EMAIL,
565+
},
566+
activeProfile: config.DefaultProfileName,
567+
isValid: true,
568+
},
569+
{
570+
description: "base, custom profile",
571+
keys: getAllAuthFieldKeys(),
572+
activeProfile: "test-profile",
573+
isValid: true,
574+
},
575+
{
576+
description: "missing keys, custom profile",
577+
keys: []authFieldKey{
578+
ACCESS_TOKEN,
579+
SERVICE_ACCOUNT_EMAIL,
580+
},
581+
activeProfile: config.DefaultProfileName,
582+
isValid: true,
583+
},
584+
{
585+
description: "invalid profile",
586+
activeProfile: "INVALID",
587+
isValid: false,
588+
},
589+
}
590+
591+
for _, tt := range tests {
592+
t.Run(tt.description, func(t *testing.T) {
593+
keyring.MockInit()
594+
595+
// Append random string to auth field key and value to avoid conflicts
596+
testValue1 := fmt.Sprintf("value-1-keyring-%s", time.Now().Format(time.RFC3339))
597+
598+
// Append random string to profile name to avoid conflicts
599+
tt.activeProfile = makeProfileNameUnique(tt.activeProfile)
600+
601+
for _, key := range tt.keys {
602+
err := setAuthFieldInKeyring(tt.activeProfile, key, testValue1)
603+
if err != nil {
604+
t.Fatalf("Failed to set \"%s\" as \"%s\": %v", key, testValue1, err)
605+
}
606+
}
607+
608+
err := DeleteProfileFromKeyring(tt.activeProfile)
609+
if err != nil {
610+
if tt.isValid {
611+
t.Fatalf("Failed to delete profile \"%s\" from keyring: %v", tt.activeProfile, err)
612+
}
613+
return
614+
}
615+
616+
if !tt.isValid {
617+
t.Fatalf("Expected error when deleting profile \"%s\" from keyring, got none", tt.activeProfile)
618+
}
619+
620+
for _, key := range tt.keys {
621+
// Check if key still exists
622+
_, err = getAuthFieldFromKeyring(tt.activeProfile, key)
623+
if err == nil {
624+
t.Fatalf("Key \"%s\" still exists in keyring after profile deletion", key)
625+
}
626+
}
627+
})
628+
}
629+
}
630+
471631
func TestSetGetAuthFieldEncodedTextFile(t *testing.T) {
472632
var testField1 authFieldKey = "test-field-1"
473633
var testField2 authFieldKey = "test-field-2"
@@ -772,15 +932,6 @@ func TestGetProfileEmail(t *testing.T) {
772932
}
773933
}
774934

775-
func deleteAuthFieldInKeyring(activeProfile string, key authFieldKey) error {
776-
if activeProfile != config.DefaultProfileName {
777-
activeProfileKeyring := filepath.Join(keyringService, activeProfile)
778-
return keyring.Delete(activeProfileKeyring, string(key))
779-
}
780-
781-
return keyring.Delete(keyringService, string(key))
782-
}
783-
784935
func deleteAuthFieldInEncodedTextFile(activeProfile string, key authFieldKey) error {
785936
err := createEncodedTextFile(activeProfile)
786937
if err != nil {

0 commit comments

Comments
 (0)