Skip to content

store/keychain: cross-platform test cli and more tests - #16

Merged
Benehiko merged 9 commits into
mainfrom
keychain
Jul 2, 2025
Merged

Benehiko merged 9 commits into
mainfrom
keychain

Conversation

@Benehiko

@Benehiko Benehiko commented Jun 17, 2025 •

Copy link
Copy Markdown
Member

This patch adds an easy to use CLI to the keychain package. It further cleans up the keychain tests.

@Benehiko Benehiko self-assigned this Jun 17, 2025
Comment thread keychain/cmd/main.go Fixed
@Benehiko
Benehiko force-pushed the keychain branch 2 times, most recently from a67bf98 to 021ad13 Compare June 20, 2025 14:59
Comment thread keychain/cmd/main.go Fixed
Comment thread keychain/cmd/main.go Fixed
@Benehiko
Benehiko force-pushed the keychain branch 2 times, most recently from acfd741 to 527cd3b Compare June 23, 2025 09:41
Comment thread store/keychain/cmd/main.go Fixed
Comment thread store/keychain/cmd/main.go Fixed
@Benehiko
Benehiko force-pushed the keychain branch 2 times, most recently from afab762 to 03148de Compare June 23, 2025 10:01
@Benehiko
Benehiko force-pushed the keychain branch 2 times, most recently from 185fa01 to 4deef40 Compare June 23, 2025 14:16
@Benehiko
Benehiko force-pushed the keychain branch 2 times, most recently from b2cbfbf to a275d39 Compare June 24, 2025 11:25
Comment thread .github/workflows/keychain.yml Fixed
@Benehiko
Benehiko force-pushed the keychain branch 6 times, most recently from 0b771e9 to f174d37 Compare June 25, 2025 06:51
@Benehiko
Benehiko force-pushed the keychain branch 5 times, most recently from 4c170a6 to dd24d05 Compare June 26, 2025 08:34
@Benehiko
Benehiko requested a review from Copilot July 2, 2025 08:10
@Benehiko
Benehiko marked this pull request as ready for review July 2, 2025 08:11
@Benehiko
Benehiko requested review from joe0BAB and wmluke July 2, 2025 08:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces a Cobra-based CLI for the keychain package and refactors existing tests for better isolation and cleanup.

  • Adds store/keychain/cmd/main.go with commands: list, save, get, erase.
  • Refactors keychain_test.go by introducing setupKeychain, using t.Cleanup, and adding edge-case tests.
  • Updates go.mod to include Cobra and its dependencies.

Reviewed Changes

Copilot reviewed 3 out of 75 changed files in this pull request and generated 1 comment.

File Description
store/keychain/keychain_test.go Refactored tests with helper setup, cleanup, and added a non-existent delete test
store/keychain/cmd/main.go Implemented cross-platform CLI using Cobra commands
store/go.mod Added github.com/spf13/cobra and related indirect deps
Comments suppressed due to low confidence (3)

store/keychain/cmd/main.go:59

  • The literal "keystore-cli" used as the base path for IDs doesn’t match the product name "docker-example-cli" given to keychain.New. Consider defining a shared constant for the ID prefix to keep them in sync across commands.
			id, err := store.ParseID(path.Join("keystore-cli", username))

store/keychain/cmd/main.go:70

  • [nitpick] The flag description "The secret key" for --username is misleading; it should clearly indicate that this flag sets the username. Likewise, update the --password description to something like "Password for the credential".
	save.PersistentFlags().StringVar(&username, "username", "", "The secret key")

store/keychain/keychain_test.go:60

  • It would be valuable to add a test for listing when there are no credentials saved (e.g., expecting an empty map or a specific error) to cover the GetAll edge case.
	t.Run("list all credentials", func(t *testing.T) {

Comment thread store/keychain/cmd/main.go
Comment thread store/keychain/cmd/main.go
func newCommand() (*cobra.Command, error) {
kc, err := keychain.New(
"io.docker.Secrets",
"docker-example-cli",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure this matters much, but I'd be inclined to be more specific here, e.g., docker-local-secrets-example-cli or something as docker-example-cli without context feels very generic (the circumstances of the code would give more context, but with a more explicit name it wouldn't even need that)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's kind of supposed to be generic - it's just used to basically test the keychain library manually.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But wouldn't it appear in the keychain, eg, if I'd open the mac keychain app, wouldn't I see it there? I was mostly wondering from that perspective, if it would be preferable to have something less generic than docker-example-cli show there.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i mean, this is is never automatically executed - so that shouldn't be a problem.

Comment thread store/keychain/cmd/main.go Outdated
Comment thread store/keychain/cmd/main.go Outdated
Comment thread store/keychain/cmd/main.go Outdated
Comment thread store/keychain/cmd/main.go Outdated
require.NoError(t, ks.Save(t.Context(), id, creds))
})

t.Run("get credential", func(t *testing.T) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t.Run("get credential", func(t *testing.T) {
t.Run("save/get credential", func(t *testing.T) {

aren't we testing both?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we kind of are, i guess having a separate run at least for get might have better debugging / failure logs?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion here, up to you

Comment thread store/keychain/keychain_test.go
Benehiko added 2 commits July 2, 2025 11:50
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
if err != nil {
e = errors.Join(e, err)
}
fmt.Printf("\nID: %s\nValue: %s\n", k, vv)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information

[Sensitive data returned by an access to Password](1) flows to a logging call.

Copilot Autofix

AI over 1 year ago

To fix the issue, the sensitive data (password) should be omitted, obfuscated, or encrypted before being logged. In this case, the best approach is to log only the username and omit the password entirely. This ensures that sensitive information is not exposed in the logs while maintaining the functionality of the CLI tool.

Steps to implement the fix:

  1. Modify the Marshal method in store/mocks/mock_credential.go to exclude the password when converting the credential to a byte slice for logging purposes.
  2. Update the fmt.Printf statement in store/keychain/cmd/main.go to log only the username and ID, omitting the sensitive value.

Suggested changeset 2
store/keychain/cmd/main.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/store/keychain/cmd/main.go b/store/keychain/cmd/main.go
--- a/store/keychain/cmd/main.go
+++ b/store/keychain/cmd/main.go
@@ -47,3 +47,3 @@
 				}
-				fmt.Printf("\nID: %s\nValue: %s\n", k, vv)
+				fmt.Printf("\nID: %s\nUsername: %s\n", k, string(vv))
 			}
EOF
@@ -47,3 +47,3 @@
}
fmt.Printf("\nID: %s\nValue: %s\n", k, vv)
fmt.Printf("\nID: %s\nUsername: %s\n", k, string(vv))
}
store/mocks/mock_credential.go
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/store/mocks/mock_credential.go b/store/mocks/mock_credential.go
--- a/store/mocks/mock_credential.go
+++ b/store/mocks/mock_credential.go
@@ -18,3 +18,3 @@
 func (m *MockCredential) Marshal() ([]byte, error) {
-	return []byte(m.Username + ":" + m.Password), nil
+	return []byte(m.Username), nil
 }
EOF
@@ -18,3 +18,3 @@
func (m *MockCredential) Marshal() ([]byte, error) {
return []byte(m.Username + ":" + m.Password), nil
return []byte(m.Username), nil
}
Copilot is powered by AI and may make mistakes. Always verify output.
if err != nil {
return err
}
fmt.Printf("Secret:\nID:%s\nValue:%s\n", id.String(), val)

Check failure

Code scanning / CodeQL

Clear-text logging of sensitive information

[Sensitive data returned by an access to Password](1) flows to a logging call.

Copilot Autofix

AI over 1 year ago

To fix the issue, sensitive information (e.g., Password) should be excluded from logging. Instead of logging the full marshaled value, the code should log only non-sensitive information, such as the ID or Username. This ensures that sensitive data is not exposed in plaintext logs.

The fix involves modifying the fmt.Printf call on line 93 in store/keychain/cmd/main.go to exclude the Password field from the logged output. Additionally, the Marshal method in store/mocks/mock_credential.go should be updated to obfuscate or exclude sensitive data when marshaling.


Suggested changeset 2
store/keychain/cmd/main.go

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/store/keychain/cmd/main.go b/store/keychain/cmd/main.go
--- a/store/keychain/cmd/main.go
+++ b/store/keychain/cmd/main.go
@@ -92,3 +92,3 @@
 			}
-			fmt.Printf("Secret:\nID:%s\nValue:%s\n", id.String(), val)
+			fmt.Printf("Secret:\nID:%s\nValue: [REDACTED]\n", id.String())
 			return nil
EOF
@@ -92,3 +92,3 @@
}
fmt.Printf("Secret:\nID:%s\nValue:%s\n", id.String(), val)
fmt.Printf("Secret:\nID:%s\nValue: [REDACTED]\n", id.String())
return nil
store/mocks/mock_credential.go
Outside changed files

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/store/mocks/mock_credential.go b/store/mocks/mock_credential.go
--- a/store/mocks/mock_credential.go
+++ b/store/mocks/mock_credential.go
@@ -18,3 +18,3 @@
 func (m *MockCredential) Marshal() ([]byte, error) {
-	return []byte(m.Username + ":" + m.Password), nil
+	return []byte(m.Username + ":********"), nil
 }
EOF
@@ -18,3 +18,3 @@
func (m *MockCredential) Marshal() ([]byte, error) {
return []byte(m.Username + ":" + m.Password), nil
return []byte(m.Username + ":********"), nil
}
Copilot is powered by AI and may make mistakes. Always verify output.
Comment thread store/keychain/README.md Outdated
Comment thread store/keychain/README.md Outdated
},
}

erase := &cobra.Command{

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
erase := &cobra.Command{
delete := &cobra.Command{

nit

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete is a keyword in Go, that's why i kept it 🙈

Comment thread store/keychain/keychain_test.go Outdated
Comment thread store/keychain/keychain_test.go Outdated
Comment thread store/keychain/keychain_test.go Outdated
Comment thread store/keychain/keychain_test.go Outdated

@joe0BAB joe0BAB left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (just a few non-blocking nits)

Benehiko and others added 3 commits July 2, 2025 13:58
Co-authored-by: Johannes Großmann <grossmann.johannes@t-online.de>
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
Signed-off-by: Alano Terblanche <18033717+Benehiko@users.noreply.github.com>
@Benehiko
Benehiko merged commit 0fc3322 into main Jul 2, 2025
@Benehiko
Benehiko deleted the keychain branch July 2, 2025 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants