Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(secrets): support for csi directories #565

Merged
merged 9 commits into from
Oct 20, 2022

Conversation

Tediferous
Copy link
Contributor

@Tediferous Tediferous commented Sep 14, 2022

Closes #

πŸ’Έ TL;DR

Allow baseplate go to read secrets from a vault csi directory

Jira

πŸ§ͺ Testing Steps / Validation

βœ… Checks

  • CI tests (if present) are passing
  • Adheres to code style for repo
  • Contributor License Agreement (CLA) completed if not a Reddit employee

return nil
}
// parse file
file, err := os.Open(path)
Copy link
Member

@fishy fishy Sep 14, 2022

Choose a reason for hiding this comment

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

you actually need to use dir.Open instead of os.Open (the path is relative inside the fs)

Copy link
Member

Choose a reason for hiding this comment

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

also you did not close the file :)

@Tediferous Tediferous marked this pull request as ready for review September 15, 2022 13:40
@Tediferous Tediferous requested a review from a team as a code owner September 15, 2022 13:40
@Tediferous Tediferous requested review from konradreiche, mterwill, ghirsch-reddit and fishy and removed request for a team September 15, 2022 13:40
Copy link
Member

@fishy fishy left a comment

Choose a reason for hiding this comment

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

can you please also add some unit tests for the directory case?

return nil
}
// parse file
file, err := fs.ReadFile(dir, path)
Copy link
Member

Choose a reason for hiding this comment

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

read the file fully into memory then use bytes.NewReader is very inefficient. just use d.Open, defer close after error check, would be much better.

secrets/store.go Outdated
@@ -41,13 +43,22 @@ func NewStore(ctx context.Context, path string, logger log.Wrapper, middlewares
store := &Store{
secretHandlerFunc: nopSecretHandlerFunc,
}
parser := store.parser
Copy link
Member

Choose a reason for hiding this comment

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

nit: move this to right before line 53 instead.

Copy link
Contributor

@ghirsch-reddit ghirsch-reddit left a comment

Choose a reason for hiding this comment

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

Agreed with Yuxuan's comment about the fs.ReadFile call, but otherwise lgtm

Ted Dorfeuille added 2 commits September 15, 2022 16:55
}
for _, tt := range tests {
t.Run(
tt.name,
Copy link
Member

Choose a reason for hiding this comment

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

this will run the subtests with the same name as from line 132. which will make the output very confusing.

either construct the name to add -file/-dir suffix (e.g. make line 132 tt.name + "-file" and here tt.name + "-dir", or run another level of subtests with names file/dir.

I would strongly prefer to add another level of subtests. you can also make it another level of for loop to reuse the majority of the code:

	for _, tt := range tests {
		t.Run(
			tt.name,
			func(t *testing.T) {
				for label, path := range map[string]string{
					"file": tmpPath,
					"dir": dirCSI,
				} {
					t.Run(label, func(t *testing.T) {
						store, err := secrets.NewStore(context.Background(), path, log.TestWrapper(t))
						if err != nil {
							t.Fatal(err)
						}
						t.Cleanup(func() { store.Close() })

						secret, err := store.GetSimpleSecret(tt.key)
						if tt.expectedError == nil && err != nil {
							t.Fatal(err)
						}
						if tt.expectedError != nil && err.Error() != tt.expectedError.Error() {
							t.Fatalf("expected error %v, actual: %v", tt.expectedError, err)
						}
						if !reflect.DeepEqual(secret, tt.expected) {
							t.Fatalf("expected %+v, actual: %+v", tt.expected, secret)
						}
					})
				}
			},
		)
	}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

you are correct

Copy link
Member

@mterwill mterwill left a comment

Choose a reason for hiding this comment

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

A few style/readability nits, otherwise LGTM.

secrets/secrets.go Outdated Show resolved Hide resolved
Comment on lines 270 to 271
// NewDirSecrets parses a directory and returns its secrets
func NewDirSecrets(dir fs.FS) (*Secrets, error) {
Copy link
Member

Choose a reason for hiding this comment

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

This stutters – secrets.NewDirSecrets. Perhaps secrets.FromDir?

secrets/secrets.go Outdated Show resolved Hide resolved
var secretFile CSIFile
err = json.NewDecoder(file).Decode(&secretFile)
if err != nil {
return err
Copy link
Member

Choose a reason for hiding this comment

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

πŸ”• bare returns like this can make errors difficult to trace back if they don't contain sufficient context. I'm not going to audit everything in here, but something to keep in mind for the future. Instead:

a) if the error message contains sufficient context, add a comment to let code reviewers and future readers know that you thought about this:

return err // contains context

or, b) wrap the error with a helpful message:

return fmt.Errorf("decoding %q: %s", path, err)

Copy link
Member

Choose a reason for hiding this comment

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

agreed but we should use %w for err.

return nil
},
)
return secretsDocument, err
Copy link
Member

Choose a reason for hiding this comment

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

Unless you explicitly need the return value in the error case, it's idiomatic to return nil, err in the multi-return error case. The error and the return value are generally considered to be mutually exclusive and this pattern makes the intended use explicit and lowers overall cognitive overhead. (In this case you'd also have to adjust the signature to return a *Document)

"renewable": false,
"data": {
"type": "simple",
"value": "Y2RvVXhNMVdsTXJma3BDaHRGZ0dPYkVGSg==",
Copy link
Member

Choose a reason for hiding this comment

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

Sanity check: this isn't a real secret, right? Looks more random than the rest.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I dont know, I copied this from the other example secret that this test was already using

Copy link
Member

Choose a reason for hiding this comment

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

I think it's a valid secret that's only used in unit tests. @pacejackson might know more of the origin of it πŸ˜…

I'm 99% sure it's not something we used in prod.

@@ -298,3 +321,35 @@ func NewSecrets(r io.Reader) (*Secrets, error) {
}
return secrets, nil
}

func csiPathParser(dir fs.FS) (Document, error) {
Copy link
Member

Choose a reason for hiding this comment

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

πŸ”•

Suggested change
func csiPathParser(dir fs.FS) (Document, error) {
// walkCSIDirectory ...
func walkCSIDirectory(dir fs.FS) (*Document, error) {

Tediferous and others added 2 commits September 16, 2022 14:44
Co-authored-by: Matt Terwilliger <matt@terwilligers.com>
@fishy
Copy link
Member

fishy commented Oct 20, 2022

Oh sorry I didn't realize that you already got approvals from all reviewers. gonna merge this.

@fishy fishy merged commit 155114b into reddit:master Oct 20, 2022
kylelemons added a commit that referenced this pull request Oct 25, 2022
* Upgrade thrift to 0.17.0

This allows us to remove tDuplicateToProtocol and getClientError
implementation as they are in thrift v0.17.0 now.

There's no breaking changes between 0.16.0 and 0.17.0 regarding go
library/compiler.

* breakerbp: Fix prometheus gauge

In the current implementation, the gauge value is only set when the
state of the breaker changes. Which means if a breaker never got
tripped, we would not report the gauge value at all.

Set an initial value of 1 in constructor.

* Update gRPC metrics to match v2 and spec (#572)

* feat(secrets): support for csi directories (#565)

Co-authored-by: Ted Dorfeuille <ted.dorfeuille@reddit.com>
Co-authored-by: Matt Terwilliger <matt@terwilligers.com>

Co-authored-by: Yuxuan 'fishy' Wang <yuxuan.wang@reddit.com>
Co-authored-by: Kyle Lemons <kyle.lemons@reddit.com>
Co-authored-by: Ted <Tediferous@users.noreply.github.com>
Co-authored-by: Ted Dorfeuille <ted.dorfeuille@reddit.com>
Co-authored-by: Matt Terwilliger <matt@terwilligers.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants