-
Notifications
You must be signed in to change notification settings - Fork 13
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
Implement detection of changes in K8s Secret content with UT #448
Conversation
10675f1
to
054f17c
Compare
cdc1563
to
0e2ffdf
Compare
@@ -372,6 +375,7 @@ func TestProvide(t *testing.T) { | |||
for secretName, secretData := range tc.k8sSecrets { | |||
mocks.kubeClient.AddSecret(secretName, secretData) | |||
} | |||
prevSecretsChecksums = map[string]utils.Checksum{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't look like this is used anywhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed for TestProvide() to zero out prevSecretsChecksums so that it writes values in this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooh.... I'm glad @szh asked this question!!! I don't think we should be using a global variable for prevSecretsChecksums
here, or for the Push-to-File provider either. The issue that we might face with using global variables is that if our UT test cases are ever run in parallel, then one test case could potentially stomp on another test case's values in the global prevSecretsChecksums
.
I believe the prevSecretsChecksums
should be moved to the K8sProvider
struct. Each UT test case should be creating its own K8sProvider
to test with, so each one should be created with its own prevSecretsChecksums
. Thinking about this a bit more, this would also help in the future if we should ever need to run multiple K8sProviders
in parallel.
We need to fix this for the Push-to-File provider as well. I don't know if you want to tackle that here or separately.
) | ||
|
||
type Checksum []byte | ||
func FileChecksum(buf *bytes.Buffer) (Checksum, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed this PR decreases the code coverage a bit. Should we add tests for this file?
ROTATION.md
Outdated
@@ -135,7 +141,6 @@ This feature is a **Community** level project that is still under development. | |||
There could be changes to the documentation so please check back often for updates and additions. | |||
Future enhancements to this feature will include: | |||
|
|||
- Support for secrets rotation of Kubernetes secrets | |||
- atomic writes for multiple Conjur secret values | |||
- reporting of multiple errored secret variables for bulk Conjur secret retrieval and selective deletion of secret values from files | |||
- atomic write of secret files |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "atomic write of secret files" is implemented now as well, so we might as well delete that item from this list of future enhancements.
@@ -372,6 +375,7 @@ func TestProvide(t *testing.T) { | |||
for secretName, secretData := range tc.k8sSecrets { | |||
mocks.kubeClient.AddSecret(secretName, secretData) | |||
} | |||
prevSecretsChecksums = map[string]utils.Checksum{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oooh.... I'm glad @szh asked this question!!! I don't think we should be using a global variable for prevSecretsChecksums
here, or for the Push-to-File provider either. The issue that we might face with using global variables is that if our UT test cases are ever run in parallel, then one test case could potentially stomp on another test case's values in the global prevSecretsChecksums
.
I believe the prevSecretsChecksums
should be moved to the K8sProvider
struct. Each UT test case should be creating its own K8sProvider
to test with, so each one should be created with its own prevSecretsChecksums
. Thinking about this a bit more, this would also help in the future if we should ever need to run multiple K8sProviders
in parallel.
We need to fix this for the Push-to-File provider as well. I don't know if you want to tackle that here or separately.
@@ -372,6 +375,7 @@ func TestProvide(t *testing.T) { | |||
for secretName, secretData := range tc.k8sSecrets { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While we're changing these unit tests, would you mind modifying the way that we're invoking test cases so that each is called via t.Run(tc.desc ...)
. What the iterations would look like is:
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
// Set up test case
mocks := newTestMocks()
. . .
The advantage to doing this is that if/when UT failures occur, the tc.desc
is displayed prominently in the failure summary, and it makes it very obvious which test case(s) have failed.
Also, I believe that we would need to run the test cases via t.Run(...)
if we should ever want to run the test cases in parallel (reference: https://eleni.blog/2019/05/11/parallel-test-execution-in-go/).
@@ -383,3 +387,91 @@ func TestProvide(t *testing.T) { | |||
} | |||
} | |||
} | |||
|
|||
func Test_secrets_contentChanges(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ruh-Roh, the name of this test function uses snake_case
. (Function name should be TestSecretContentChanges
).
I fear we've been doing too many context switches between Bash and Go.
}, | ||
expectedMissingValues{} ) (t, mocks, err, desc) | ||
|
||
// Call Provide again, verify is doesn't try to update the secret |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, should be "verify it doesn't ...".
|
||
// Call Provide again, verify is doesn't try to update the secret | ||
// as there should be an error if it tried to write the secrets | ||
denyK8sUpdate = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a clever way to detect that it's not trying to update! :)
expectedK8sSecrets{ | ||
"k8s-secret1": {"secret1": "secret-value1"}, | ||
}, | ||
expectedMissingValues{} ) (t, mocks, err, desc) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something that might be worth considering here... this test involves a whole bunch of operations, and if when there's a test failure, it won't be immediately obvious which assert in this test is failing (and where in the sequence of operations it's failing), without having to match up line numbers in the source code. What you could do is to modify the desc
string as you work your way through the sequence. That way, the failure summary for the assert that fails will provide us with details on where exactly it's failing.
0e2ffdf
to
70f52e0
Compare
70f52e0
to
3454846
Compare
3379346
to
6317dc6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great. I left a couple docs comments.
@@ -71,7 +71,13 @@ There are two new annotations introduced and one annotation is updated. | |||
Prerequisites: | |||
|
|||
Requires secrets-provider-for-k8s v1.4.0 or later. | |||
|
|||
<details><summary>For Push to File mode</summary> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there needs to be an empty line after the <summary>
block. I think this is causing the hyperlinks to not render as links.
See here for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
CHANGELOG.md
Outdated
- Kubernetes Secrets are only updated when there are changes when secrets rotation is enabled. | ||
[cyberark/secrets-provider-for-k8s#448](https://github.com/cyberark/secrets-provider-for-k8s/pull/448) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the changelog entries for the previous release, notably for for #432, and given that K8s secrets wasn't previously supported, I wonder if we should replace this with "Secrets rotation is now supported for Kubernetes Secrets"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about "Adds support for secrets rotation with Kubernetes Secrets."
98414de
to
90a1fae
Compare
90a1fae
to
e7bd95e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Code Climate has analyzed commit e7bd95e and detected 0 issues on this pull request. The test coverage on the diff in this pull request is 94.8% (50% is the threshold). This pull request will bring the total coverage in the repository to 89.6% (-0.2% change). View more on Code Climate. |
Desired Outcome
The Kubernetes secrets should only be updated when there is new content.
Implemented Changes
Updated to detect changes the k8s secrets values and Conjur secrets.
Connected Issue/Story
Resolves #[relevant GitHub issue(s), e.g. 76]
CyberArk internal issue link: ONYX-17475
Definition of Done
Changelog
CHANGELOG update
Test coverage
changes, or
Documentation
README
s) were updated in this PRBehavior
Security