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

Implement detection of changes in K8s Secret content with UT #448

Merged
merged 1 commit into from
Mar 23, 2022

Conversation

rpothier
Copy link
Contributor

@rpothier rpothier commented Mar 15, 2022

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

  • [] K8s secrets are updated only when there are changes in the k8s secrets content or Conjur secrets.

Changelog

  • The CHANGELOG has been updated, or
  • This PR does not include user-facing changes and doesn't require a
    CHANGELOG update

Test coverage

  • This PR includes new unit and integration tests to go with the code
    changes, or
  • The changes in this PR do not require tests

Documentation

  • Docs (e.g. READMEs) were updated in this PR
  • A follow-up issue to update official docs has been filed here: insert issue ID
  • This PR does not require updating any documentation

Behavior

  • This PR changes product behavior and has been reviewed by a PO, or
  • These changes are part of a larger initiative that will be reviewed later, or
  • No behavior was changed with this PR

Security

  • Security architect has reviewed the changes in this PR,
  • These changes are part of a larger initiative with a separate security review, or
  • There are no security aspects to these changes

@rpothier rpothier self-assigned this Mar 15, 2022
@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch 5 times, most recently from 10675f1 to 054f17c Compare March 17, 2022 13:47
@rpothier rpothier marked this pull request as ready for review March 17, 2022 13:47
@rpothier rpothier requested a review from a team as a code owner March 17, 2022 13:47
@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch 8 times, most recently from cdc1563 to 0e2ffdf Compare March 18, 2022 17:41
@szh szh self-requested a review March 21, 2022 15:47
@@ -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{}
Copy link
Contributor

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

Copy link
Contributor Author

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.

Copy link
Contributor

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) {
Copy link
Contributor

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
Copy link
Contributor

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{}
Copy link
Contributor

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 {
Copy link
Contributor

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) {
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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)
Copy link
Contributor

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.

@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch from 0e2ffdf to 70f52e0 Compare March 22, 2022 18:59
@rpothier rpothier marked this pull request as draft March 22, 2022 18:59
@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch from 70f52e0 to 3454846 Compare March 22, 2022 20:15
@rpothier rpothier marked this pull request as ready for review March 23, 2022 13:47
@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch 2 times, most recently from 3379346 to 6317dc6 Compare March 23, 2022 14:40
Copy link
Contributor

@szh szh left a 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>
Copy link
Contributor

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.

Copy link
Contributor Author

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
Comment on lines 15 to 16
- 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)
Copy link
Contributor

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"

Copy link
Contributor Author

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."

@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch 2 times, most recently from 98414de to 90a1fae Compare March 23, 2022 19:52
@rpothier rpothier force-pushed the 17475-detect-k8s-secrets branch from 90a1fae to e7bd95e Compare March 23, 2022 19:53
Copy link
Contributor

@szh szh left a comment

Choose a reason for hiding this comment

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

LGTM!

@codeclimate
Copy link

codeclimate bot commented Mar 23, 2022

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.

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.

3 participants