-
Notifications
You must be signed in to change notification settings - Fork 104
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
[JENKINS-42950] Support more credential masking scenarios #59
Conversation
This adds a new extension point, PatternMaskerProvider, that can be used to implement different quoting and unquoting strategies used by shells that can mangle passwords and other secrets in their output. This is used to improve credential masking in more scenarios where the secret was not intended to be seen. Co-Authored-By: Wadeck Follonier <wadeck.follonier@gmail.com>
src/main/resources/org/jenkinsci/plugins/credentialsbinding/impl/BindingStep/help.html
Outdated
Show resolved
Hide resolved
src/main/resources/org/jenkinsci/plugins/credentialsbinding/impl/BindingStep/help.html
Outdated
Show resolved
Hide resolved
src/main/resources/org/jenkinsci/plugins/credentialsbinding/impl/BindingStep/help.html
Outdated
Show resolved
Hide resolved
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.
Test failures
[2019-05-02T19:31:42.909Z] [ERROR] org.jenkinsci.plugins.credentialsbinding.impl.CredentialsMaskingBashTest.credentialsAreMaskedInLogs(org.jenkinsci.plugins.credentialsbinding.impl.CredentialsMaskingBashTest)
[2019-05-02T19:31:42.909Z] [ERROR] Run 1: CredentialsMaskingBashTest.credentialsAreMaskedInLogs credentialsAreMaskedInLogs("PjsQ&^S6nVl!NZM3RQ6)J6" <from generatePasswords[0]>)
[2019-05-02T19:31:42.909Z] [ERROR] Run 2: CredentialsMaskingBashTest.credentialsAreMaskedInLogs credentialsAreMaskedInLogs(")4a= (nG" <from generatePasswords[0]>)
[2019-05-02T19:31:42.909Z] [ERROR] Run 3: CredentialsMaskingBashTest.credentialsAreMaskedInLogs credentialsAreMaskedInLogs("YI'1JHTC{>20lSz)'.7VS5b6" <from generatePasswords[0]>)
[2019-05-02T19:31:42.909Z] [ERROR] Run 4: CredentialsMaskingBashTest.credentialsAreMaskedInLogs credentialsAreMaskedInLogs("UQjhT6"Oy04Uv{5>Op"UZ,oHh0<%" <from generatePasswords[0]>)
[2019-05-02T19:31:42.909Z] [ERROR] Run 5: CredentialsMaskingBashTest.credentialsAreMaskedInLogs credentialsAreMaskedInLogs("JR{r'u@*D<Ld"Kj^N5dkwZ*" <from generatePasswords[0]>)
Some comments in addition, esp. around test
src/test/java/org/jenkinsci/plugins/credentialsbinding/impl/CredentialsMaskingBashTest.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/BatchPatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/PatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/PatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
src/test/java/org/jenkinsci/plugins/credentialsbinding/impl/CredentialsMaskingBashTest.java
Outdated
Show resolved
Hide resolved
...est/java/org/jenkinsci/plugins/credentialsbinding/impl/CredentialsMaskingPowerShellTest.java
Outdated
Show resolved
Hide resolved
...est/java/org/jenkinsci/plugins/credentialsbinding/masking/BashPatternMaskerProviderTest.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Co-Authored-By: jvz <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Alright, I think I've addressed all your feedback. Not sure why CI is failing as that's giving a different output than my own testing locally for bash. |
Signed-off-by: Matt Sicker <boards@gmail.com>
Perhaps because the CI build is running on Ubuntu. Your test seems to assume without checking that |
Signed-off-by: Matt Sicker <boards@gmail.com>
Good catch. I've updated the tests to change the default shell to bash. |
Seems as though the theories runner fails otherwise if the assumption is violated. Signed-off-by: Matt Sicker <boards@gmail.com>
Now I'm confused as to what's failing this time. |
@@ -52,6 +54,7 @@ | |||
@Before | |||
public void setUp() { | |||
assumeThat("bash", is(executable())); | |||
j.jenkins.getDescriptorByType(Shell.DescriptorImpl.class).setShell(Executables.getPathToExecutable("bash")); |
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.
Due to that, you remove the test for "pure Shell" right? But we want to support it along Bash, Batch and PowerShell.
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.
Not sure what the issue is—this is a new test suite.
Non-bash implementations of Bourne shell do not perform any quoting of
echoed commands. It works more like Windows Batch where it just echoes out
what you typed. I don’t think it’s documented here, but I did find that
during discovery.
On Mon, May 6, 2019 at 06:50, Wadeck Follonier ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In
src/test/java/org/jenkinsci/plugins/credentialsbinding/masking/BashPatternMaskerProvider2Test.java
<#59 (comment)>
:
> @@ -52,6 +54,7 @@
@before
public void setUp() {
assumeThat("bash", is(executable()));
+ j.jenkins.getDescriptorByType(Shell.DescriptorImpl.class).setShell(Executables.getPathToExecutable("bash"));
Due to that, you remove the test for "pure Shell" right? But we want to
support it along Bash, Batch and PowerShell.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#59 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAGBF2ZOKHXXZMIRZYRALD3PUALP3ANCNFSM4HKFF2XA>
.
--
Matt Sicker
Senior Software Engineer, CloudBees
|
@jvz Re Shell => so a non-regression test can be written for such case easily |
That would be me. I have not yet had time to review. |
See also #55. |
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.
Some questions and minor comments. Basically looks good to me except for the one decision to bake Pattern.quote
into the SPI, which seems unnecessary and undesirable.
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/PatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/PatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/PatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/PatternMaskerProvider.java
Outdated
Show resolved
Hide resolved
* this will work in every possible situation. Another consequence of this ordering is that inputs that require | ||
* quoting will be masked before a substring of the input was matched, thus avoiding leakage of information. | ||
* For example, {@code bash -x} will only quote arguments echoed when necessary. To avoid leaking the presence or | ||
* absence of quoting, the longer form is masked. |
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.
Can you give an example of a situation where the presence or absence of quoting would be leaked otherwise? I am not sure I follow this logic. Just as an aside.
...est/java/org/jenkinsci/plugins/credentialsbinding/masking/BashPatternMaskerProviderTest.java
Outdated
Show resolved
Hide resolved
|
||
@Test | ||
public void simple_singleQuote() throws Exception { | ||
registerCredentials(SIMPLE); |
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.
Why is the Bash version using the theory system, and this is done manually? Smells like there could be some consolidation of test code.
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.
Different test authors originally. I can likely figure out how to break this into a theorized test.
...st/java/org/jenkinsci/plugins/credentialsbinding/masking/BatchPatternMaskerProviderTest.java
Outdated
Show resolved
Hide resolved
...st/java/org/jenkinsci/plugins/credentialsbinding/masking/BatchPatternMaskerProviderTest.java
Outdated
Show resolved
Hide resolved
src/test/java/org/jenkinsci/plugins/credentialsbinding/test/Executables.java
Show resolved
Hide resolved
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 do not feel there is any value I can add by reviewing
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.
Oh and you need to either delete or modify the message printed from BindingStep
after #55, since we are no longer masking only exact matches.
Co-Authored-By: Jesse Glick <jglick@cloudbees.com>
Co-Authored-By: Jesse Glick <jglick@cloudbees.com>
Co-Authored-By: Jesse Glick <jglick@cloudbees.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
This removes the exposure of Pattern.quote() in the consumer calls along with other cleanups around this idea. Signed-off-by: Matt Sicker <boards@gmail.com>
This one was moved over to LiteralSecretPatternFactory Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
I've addressed most of your review comments, @jglick. I'll take a look at improving the test differences later today. |
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/SecretPatternFactory.java
Outdated
Show resolved
Hide resolved
src/main/java/org/jenkinsci/plugins/credentialsbinding/masking/SecretPatterns.java
Outdated
Show resolved
Hide resolved
Signed-off-by: Matt Sicker <boards@gmail.com>
Updating the log message has tests? Color me surprised, ok. I'll also have a fix for that. |
Signed-off-by: Matt Sicker <boards@gmail.com>
Signed-off-by: Matt Sicker <boards@gmail.com>
@@ -146,7 +146,7 @@ | |||
+ "}", true)); | |||
WorkflowRun b = p.scheduleBuild2(0).waitForStart(); | |||
SemaphoreStep.waitForStart("basics/1", b); | |||
story.j.assertLogContains(Functions.isWindows() ? "Masking only exact matches of %USERNAME% or %PASSWORD%" : "Masking only exact matches of $USERNAME or $PASSWORD", b); | |||
story.j.assertLogContains(Functions.isWindows() ? "Masking supported pattern matches of %USERNAME% or %PASSWORD%" : "Masking supported pattern matches of $USERNAME or $PASSWORD", b); |
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.
Feel free to introduce a package-private utility method for this message to be shared between src/main/
and src/test/
.
patterns.add(quotedForm); | ||
patterns.add(surroundWithQuotes(quotedForm)); | ||
patterns.add(getUnquotedForm(input)); | ||
return patterns; |
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.
or a bit more simply
return Arrays.asList(quotedForm, surroundWithQuotes(quotedForm), getUnquotedForm(input));
Mangled secrets are not detected by Jenkins and will appear in plain text in the log file, in this case as: | ||
Mangled secrets can only be detected on a best-effort basis. By default, Jenkins will attempt to mask mangled | ||
secrets as they would appear in output of Bash and Windows batch. Without these strategies in place, mangled secrets | ||
would appear in plain text in log files. In the example above, this would result in: |
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.
BTW for natural-language text files it is a good idea to use one physical line per sentence or major phrase. Easier to review & edit.
JENKINS-42950
This adds a new extension point,
SecretPatternFactory
, that can be used to implement different quoting and unquoting strategies used by shells that can mangle passwords and other secrets in their output. This is used to improve credential masking in more scenarios where the secret was not intended to be seen.Co-Authored-By: @Wadeck
@reviewbybees @jeffret-b @jglick @jtnord @daniel-beck