Skip to content

Conversation

@jimklimov
Copy link
Contributor

@jimklimov jimklimov commented Nov 21, 2022

As detailed in https://issues.jenkins.io/browse/JENKINS-70101 I've hit a problem using certificate-based user authentication in http-request-plugin (noticed as part of my work on https://issues.jenkins.io/browse/JENKINS-70000 in jenkinsci/http-request-plugin#120 but also reproduced with latest 1.16 release of that plugin).

After a week of reproductions and tracing across different plugins, the root of the problem crystallized as the use of SecretBytes in UploadedKeyStoreSource and effective lack of special snapshot() support. As a consequence, serialized copies of the key store used the same SecretBytes as on the Jenkins Controller, but being on a different JVM in the remote agent case, they used a different instance of the static KEY field with its own secret field. Although the SecretBytes are diligently copied (took a lot of effort to confirm that as seen in sibling branch https://github.com/jimklimov/credentials-plugin/tree/JENKINS-70101-trace), they are unreadable on the remote agent.

During investigation I found that credentials-plugin did have an implementation for the Certificate Credentials Snapshot Taker, but it was removed by 40d0b5c as part of deprecation of FileOnMasterKeyStoreSource subclass. Also an earlier history of the plugin involved the Secret class which effectively stores a base64 string and only encodes/decodes it on demand -- this was superseded by SecretBytes but some handling for conversion from older versions remained. This code proved to be a good starting point for fixing the problem, although not without some further work:

  • originally it consulted isSnapshotSource (forced true for UploadedKeyStoreSource subclass) and just returned the original credential if so;
  • even with that check disabled, the snapshot used SecretBytes for the copied key store and suffered the same fate - not usable on agent.

This PR adds tests (failing at first to confirm the problem), makes use of older codebases and new verified fixes:

  • UploadedKeyStoreSource.isSnapshotSource() depends on Channel.current() == null (so for remoting-related snapshots it is false and shortcuts to return this are not taken)
  • CertificateCredentialsSnapshotTaker was revived as a separate source file and standalone class, similar to existing UsernamePasswordCredentialsSnapshotTaker
  • UploadedKeyStoreSource was modified to handle again a Secret uploadedKeyStore field (and provide data from it if SecretBytes uploadedKeyStoreBytes are currently null). As part of that, transient and final modifiers on these fields had to go.
  • CertificateCredentialsSnapshotTaker was modified to create the new UploadedKeyStoreSource instance with Secret version rather than SecretBytes (as CredentialsSnapshotTaker docs stipulate, "all the details are captured within the credential")

Thanks to @mawinter69 and @slide for bright ideas and pointers, and general sympathy as I woed on the chat :)

Separately note that this PR adds tests using a separate JVM for the build agent to reproduce the problem. This code may be worth exporting into some JenkinsAgentRule if someone is up for it.

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests - that demonstrates feature works or fixes the issue

NOTE: I'll post commits in several phases, so CI has its chance to fail with the tests and show the original problem in logs.

@jimklimov jimklimov requested a review from a team as a code owner November 21, 2022 13:53
@jimklimov
Copy link
Contributor Author

Problem exposed in build logs, e.g. in https://github.com/jenkinsci/credentials-plugin/pull/391/checks?check_run_id=9617279731 :

[2022-11-21T14:02:34.841Z] Querying HTTPS with cert...
[2022-11-21T14:02:34.841Z] [Pipeline] httpRequest
[2022-11-21T14:02:34.841Z] HttpMethod: GET
[2022-11-21T14:02:34.841Z] URL: https://github.xcom/api/v3
[2022-11-21T14:02:34.841Z] Content-Type: application/x-www-form-urlencoded; charset=ISO-8859-1
[2022-11-21T14:02:34.841Z] Using authentication: myCert
[2022-11-21T14:02:34.841Z] [Pipeline] }
[2022-11-21T14:02:34.841Z] [Pipeline] // node
[2022-11-21T14:02:34.841Z] [Pipeline] End of Pipeline
[2022-11-21T14:02:34.841Z] javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
[2022-11-21T14:02:34.841Z] 	at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:975)
[2022-11-21T14:02:34.841Z] 	at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:1056)
[2022-11-21T14:02:34.841Z] 	at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:853)
[2022-11-21T14:02:34.841Z] 	at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:446)
[2022-11-21T14:02:34.841Z] 	at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202)
[2022-11-21T14:02:34.841Z] 	at com.cloudbees.plugins.credentials.SecretBytes.getPlainData(SecretBytes.java:140)
[2022-11-21T14:02:34.841Z] Also:   hudson.remoting.Channel$CallSiteStackTrace: Remote call to worker
[2022-11-21T14:02:34.841Z] 		at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1784)
[2022-11-21T14:02:34.841Z] 		at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:356)
[2022-11-21T14:02:34.841Z] 		at hudson.remoting.Channel.call(Channel.java:1000)
[2022-11-21T14:02:34.841Z] 		at jenkins.plugins.http_request.HttpRequestStep$Execution.run(HttpRequestStep.java:404)
[2022-11-21T14:02:34.841Z] 		at jenkins.plugins.http_request.HttpRequestStep$Execution.run(HttpRequestStep.java:383)
[2022-11-21T14:02:34.841Z] 		at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:47)
[2022-11-21T14:02:34.841Z] 		at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
[2022-11-21T14:02:34.841Z] Caused: java.lang.Error
[2022-11-21T14:02:34.841Z] 	at com.cloudbees.plugins.credentials.SecretBytes.getPlainData(SecretBytes.java:142)
[2022-11-21T14:02:34.841Z] 	at com.cloudbees.plugins.credentials.SecretBytes.getPlainData(SecretBytes.java:233)
Output truncated.

Will post the fix commits now :)

@jimklimov
Copy link
Contributor Author

Tests fixed. Now posting the final touch, to make them quieter. This passes - and good to merge (on my side) :)

@slide
Copy link
Member

slide commented Nov 21, 2022

@jenkinsci/core-security-review Should probably review this.

@jimklimov
Copy link
Contributor Author

jimklimov commented Nov 21, 2022

Yep. In particular, I wonder if it is okay to leave it like this (possibly storing keystore data "plaintext" in a Secret which still needs a password to read, vs. SecretBytes all the time - only in cases where UploadedKeyStoreSource was made by constructor with Secret in the first place, e.g. via snapshot() in now-existing codebase; other cases gotta have disappeared since 2019).

I have a further effort to force conversion from Secret to SecretBytes on first read, if we are in context where Channel is not null and JenkinsJVM indicates running not on a controller. It complicates things a bit, does not seem to break anything, and I have no idea if it actually takes effect (never saw the logs it is supposed to emit in my local branch - not as MVN log, not as pipeline log, not as agent log...) and also there is some indefinite timeframe where the Secret is used by the class instance before the first read. Probably someone with debug privileges can un-private the field to read it, but that's a pretty contrived attack and probably SecretBytes are not much safer in that situation.

@jimklimov
Copy link
Contributor Author

jimklimov commented Nov 28, 2022

@jenkinsci/core-security-review Gentle bump :)

@yaroslavafenkin
Copy link
Contributor

Hey @jimklimov, we've noticed the issue. We'll try to review it if/when time permits.

…enkinsci#391 discussion

Specifically the jenkinsci#391 (comment)
note that the original comment about `values[]` seems wrong, and
comments before that.

Signed-off-by: Jim Klimov <[email protected]>
jimklimov and others added 3 commits January 2, 2026 18:44
…) instead of custom code [JENKINS-70101]

Signed-off-by: Jim Klimov <[email protected]>
…nAgent() proposed in PR jenkinsci#391 discussion

Rearranged from commit 4ee16f3 posted
in https://github.com/dwnusbaum/credentials-plugin/tree/JENKINS-70101
(initially as a simpler bug repro case than CredentialsInPipelineTest).

Co-authored-by: Devin Nusbaum <[email protected]>
Signed-off-by: Jim Klimov <[email protected]>
… agent after test case [JENKINS-70101]

Signed-off-by: Jim Klimov <[email protected]>
@jimklimov
Copy link
Contributor Author

jimklimov commented Jan 2, 2026

Note for posterity: for a long time, it sufficed in practice to merge master-branch increments and reap the benefits of the PR'ed change for our local workflows (regardless of it being or not pedantically "wrong", per review comments above, it worked). Alas in the past couple of weeks, with the ban on JUnit 4 the existing test cases broke, a quick refactor did not help, so finally (long overdue) I'm trying to dig into the requested fixes to the PR, piece by piece. At least with the New Year holidays got a few cycles away from dayjob churn to dedicate some attention to this issue, once in a few years.

As I am still not much of a Java developer, I am struggling to make practical sense of some short suggestions posted earlier; consider me obtuse if needed:

create a different Implementation of the interface that is self contained for the snapshot.
having this here, will cause it to be persisted in addition to the secret bytes.
Um, pardon the stupid question - but which interface and for which class? A different CertificateCredentialsImpl look-alike which other consumers would have to be changed to use? That kind of defeats the purpose of being a fix for a bug with the existing version.

Any calling code (about to run on an agent) should just call the snapshot taker to get a snapshot before using any credential.
Again, does this imply changing the unknown amount of other plugins and other consumers (who is the "calling code" in that sentence)?

you should create a new implementation of StandardCertificateCredentials and return that. Putting the extra info and logic into the current Implementation is not the correct path.
Is this an answer to questions I had above about changes to the other consumers? E.g. if they expect some implementation of an interface, they would get a new class instance with a fix (whether implementation of an interface, or a derived class so it still counts as a sort of StandardCertificateCredentials for whoever expects that more explicitly)?

  • Suggestions to "write a Step" and "use TestExtensions" sadly still do not ring a bell much. I looked around and saw some RealJenkinsExtension mentions for FIPS tests in https://github.com/jenkinsci/credentials-plugin/pull/652/changes but that is not compatible with methods I called earlier for JenkinsRule. Pointers to docs/examples would be welcome.

  • Tests using pipelines and further plugins - looking at changing that, but rather reluctantly. They do expose having or fixing the practical use-case we have with a real unmodified consumer of this plugin as a reference, to check that the fix "here only" solves their issue without looking where to fix someone else in the ecosystem...

@jimklimov
Copy link
Contributor Author

jimklimov commented Jan 3, 2026

Odd... locally test runs in IDEA failed with padding problems (maybe wrong key), but CI above passed as of https://ci.jenkins.io/job/Plugins/job/credentials-plugin/job/PR-391/20/pipeline-overview/ both on Linux and Windows workers, so I vented the questions above.

FWIW, locally it complained thusly:

[ERROR]   CredentialsInPipelineTest.testCertHttpRequestOnNodeRemote:565 unexpected build status; build log was:
...
hudson.remoting.ProxyException: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
	at java.base/com.sun.crypto.provider.CipherCore.unpad(CipherCore.java:859)
	at java.base/com.sun.crypto.provider.CipherCore.fillOutputBuffer(CipherCore.java:939)
	at java.base/com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:735)
	at java.base/com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
	at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2205)
	at app//com.cloudbees.plugins.credentials.SecretBytes.getPlainData(SecretBytes.java:144)
Also:   hudson.remoting.ProxyException: hudson.remoting.Channel$CallSiteStackTrace: Remote call to slave0
		at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1916)
		at hudson.remoting.UserRequest$ExceptionResponse.retrieve(UserRequest.java:384)
		at hudson.remoting.Channel.call(Channel.java:1108)
		at jenkins.plugins.http_request.HttpRequestStep$Execution.run(HttpRequestStep.java:405)
		at jenkins.plugins.http_request.HttpRequestStep$Execution.run(HttpRequestStep.java:384)
		at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:49)
		at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
		at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
		at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
Caused: hudson.remoting.ProxyException: java.lang.Error: javax.crypto.BadPaddingException: Given final block not properly padded. Such issues can arise if a bad key is used during decryption.
	at app//com.cloudbees.plugins.credentials.SecretBytes.getPlainData(SecretBytes.java:146)
	at app//com.cloudbees.plugins.credentials.SecretBytes.getPlainData(SecretBytes.java:237)
	at app//com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl$UploadedKeyStoreSource.getKeyStoreBytes(CertificateCredentialsImpl.java:510)
	at app//com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl$UploadedKeyStoreSource.toKeyStore(CertificateCredentialsImpl.java:544)
	at app//com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl.getKeyStore(CertificateCredentialsImpl.java:188)
	at app//jenkins.plugins.http_request.auth.CertificateAuthentication.authenticate(CertificateAuthentication.java:54)
	at app//jenkins.plugins.http_request.HttpRequestExecution.auth(HttpRequestExecution.java:467)
	at app//jenkins.plugins.http_request.HttpRequestExecution.authAndRequest(HttpRequestExecution.java:383)
	at app//jenkins.plugins.http_request.HttpRequestExecution.call(HttpRequestExecution.java:293)
	at app//jenkins.plugins.http_request.HttpRequestExecution.call(HttpRequestExecution.java:88)
	at hudson.remoting.UserRequest.perform(UserRequest.java:225)
	at hudson.remoting.UserRequest.perform(UserRequest.java:50)
	at hudson.remoting.Request$2.run(Request.java:391)
	at hudson.remoting.InterceptingExecutorService.lambda$wrap$0(InterceptingExecutorService.java:81)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
Also:   hudson.remoting.ProxyException: org.jenkinsci.plugins.workflow.actions.ErrorAction$ErrorId: 8c634bb3-a03f-40cb-a797-5ccead5f5f46
Caused: hudson.remoting.ProxyException: java.io.IOException: Remote call on slave0 failed
	at hudson.remoting.Channel.call(Channel.java:1112)
	at jenkins.plugins.http_request.HttpRequestStep$Execution.run(HttpRequestStep.java:405)
	at jenkins.plugins.http_request.HttpRequestStep$Execution.run(HttpRequestStep.java:384)
	at org.jenkinsci.plugins.workflow.steps.SynchronousNonBlockingStepExecution.lambda$start$0(SynchronousNonBlockingStepExecution.java:49)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:264)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:833)
Finished: FAILURE

...so I was afraid something in the changes to test setup (or with recent 2 weeks worth of changes merged from master branch) broke the cross-JVM data transfer back. Retrying locally with mvn package and the whole suite...

@jimklimov
Copy link
Contributor Author

jimklimov commented Jan 3, 2026

...and mvn package also complained about FIPS and Form tests (and Devin's proposed useCertificateCredentialsImplOnAgent added a few commits above):

...
[ERROR] Errors: 
[ERROR]   CertificateCredentialsImplFIPSTest.doCheckPasswordTest:43 » Step Remote step threw an exception: java.lang.IllegalStateException: Found no instances of com.cloudbees.plugins.credentials.impl.CertificateCredentialsImpl$DescriptorImpl registered (possible annotation processor issue); try using `mvn clean test -Dtest=?` rather than an IDE test runner                                                                                                                                                                   
[ERROR]   CertificateCredentialsImplTest.useCertificateCredentialsImplOnAgent:341 » IO Remote call on slave0 failed
[ERROR]   UsernamePasswordCredentialsImplFIPSTest.formValidationTest:74 » Step Remote step threw an exception: java.lang.IllegalStateException: Found no instances of com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl$DescriptorImpl registered (possible annotation processor issue); try using `mvn clean test -Dtest=?` rather than an IDE test runner                                                                                                                                                          
[ERROR]   UsernamePasswordCredentialsImplFIPSTest.invalidIsNotSavedInFIPSModeTest:49 » Step Remote step threw an exception: java.util.NoSuchElementException

…ialsImplOnRemoteAgent() vs useCertificateCredentialsImplOnBuiltinAgent()

Signed-off-by: Jim Klimov <[email protected]>
…er file names for test keystores

Note: `createTempFile()` deals with patterns like shell `mktemp`, not with exact
file names.

Signed-off-by: Jim Klimov <[email protected]>
…lugin on a remote agent JVM, note that in the thrown Error

Signed-off-by: Jim Klimov <[email protected]>
@jimklimov
Copy link
Contributor Author

Good news, even though still puzzling: as I worked on adding System.err.println() logging to trace the tests across several JVMs involved, they first indicated that unmodified bytes[] of encrypted data from the controller were seen on the agent (but using its unique KEY so not fitting the cryptotext), and then they just began to pass locally. After git stash'ing those logging fixes, the tests still pass.

Maybe somehow somewhere it loaded an older build of the plugin (the standard one without the fix) until the repetitive recompilation pushed it out?.. This makes little sense, but is the best explanation I've still got.

@jimklimov
Copy link
Contributor Author

As for dropping the dependency on http_request plugin (in tests), the setup can be inverted by moving the tests there: https://github.com/jenkinsci/http-request-plugin/blame/master/src/test/java/jenkins/plugins/http_request/HttpRequestStepCredentialsTest.java was updated with the passing half (local JVM) of this test suite years ago. But this is inherently harder to test before this PR gets merged on one hand, and essentially tests that credentials plugin is functional by code that is part of http request plugin then (it still make sense, so plugin users know which version combo works on both local and remote build agents).

jimklimov added a commit to jimklimov/http-request-plugin that referenced this pull request Jan 5, 2026
… refactor to optionally juggle withReentrability and to debug-trace withLocalCertLookup [JENKINS-70101]

Import and adapt code evicted from jenkinsci/credentials-plugin#391

Signed-off-by: Jim Klimov <[email protected]>
…t code for use of HTTP Request plugin with Credentials [JENKINS-70101]

Tests to make sure the complex call stack works properly are offloaded into
that plugin, see jenkinsci/http-request-plugin#231

Signed-off-by: Jim Klimov <[email protected]>
…d as deprecated

...to avoid a maven warning

Signed-off-by: Jim Klimov <[email protected]>
@jtnord
Copy link
Member

jtnord commented Jan 5, 2026

Note for posterity: for a long time, it sufficed in practice to merge master-branch increments and reap the benefits of the PR'ed change for our local workflows (regardless of it being or not pedantically "wrong", per review comments above, it worked). Alas in the past couple of weeks, with the ban on JUnit 4 the existing test cases broke, a quick refactor did not help, so finally (long overdue) I'm trying to dig into the requested fixes to the PR, piece by piece. At least with the New Year holidays got a few cycles away from dayjob churn to dedicate some attention to this issue, once in a few years.

As I am still not much of a Java developer, I am struggling to make practical sense of some short suggestions posted earlier; consider me obtuse if needed:

create a different Implementation of the interface that is self contained for the snapshot.
having this here, will cause it to be persisted in addition to the secret bytes.
Um, pardon the stupid question - but which interface and for which class? A different CertificateCredentialsImpl look-alike which other consumers would have to be changed to use? That kind of defeats the purpose of being a fix for a bug with the existing version.

Consumers should not be using CertificateCredentialsImpl but StandardCertificateCredentials if they are using the concrete implementation that is a bug in the consumer.
So you would Snapshot CertificateCredentialsImpl to say SelfContainedCertificateCredentialsImpl which iteself implements StandardCertificateCredentials this implementation would not be visible to create directly (no symbol, no UI etc). And if someone called snapshot on it it would be a no-op.

Any calling code (about to run on an agent) should just call the snapshot taker to get a snapshot before using any credential.
Again, does this imply changing the unknown amount of other plugins and other consumers (who is the "calling code" in that sentence)?

It should not require any changes on downstream plugins - if a plugin requires changes this to be performed then that plugin is broken and should be fixed. We should not be working around it with serialisation tricks (as this will also affect persisting to disk, causing a lot of fun and games).

see https://github.com/jenkinsci/credentials-plugin/blob/master/docs/consumer.adoc#retrieve-the-secret-from-a-specific-credentials-instance for the documentation around this.

you should create a new implementation of StandardCertificateCredentials and return that. Putting the extra info and logic into the current Implementation is not the correct path.
Is this an answer to questions I had above about changes to the other consumers? E.g. if they expect some implementation of an interface, they would get a new class instance with a fix (whether implementation of an interface, or a derived class so it still counts as a sort of StandardCertificateCredentials for whoever expects that more explicitly)?

If they expect some implementation of an interface they have a broken implementation. The interfaces exist to allow different implementations to be interchangeable. For example there are other credential providers, these may supply their own implementation of StandardCertificateCredentials.

  • Suggestions to "write a Step" and "use TestExtensions" sadly still do not ring a bell much. I looked around and saw some RealJenkinsExtensionmentions for FIPS tests in https://github.com/jenkinsci/credentials-plugin/pull/652/changes but that is not compatible with methods I called earlier forJenkinsRule`. Pointers to docs/examples would be welcome.

https://javadoc.jenkins.io/component/jenkins-test-harness/org/jvnet/hudson/test/TestExtension.html
Your Extension would then have a method that took a credentialId and an agent then you would do something like

  • obtain the credential from the credential provider
  • call snapshot
  • pass that snapshotted credential to create a new MasterToSlaveCallable (you will need another new class for this)
  • pass that new object to the remote agent (theAgent.getComputer().getChannel().call(it))
  • the call method should verify the credential is OK - can be using regular java code..) and throw exceptions if it is not.
  • then in your test you would inside a JenkinsRule step run something like ExtensionList.lookupSingleton(MyTestExtension.class).testSnapShot("credentialId", theAgent)
  • Tests using pipelines and further plugins - looking at changing that, but rather reluctantly. They do expose having or fixing the practical use-case we have with a real unmodified consumer of this plugin as a reference, to check that the fix "here only" solves their issue without looking where to fix someone else in the ecosystem...

@jimklimov
Copy link
Contributor Author

jimklimov commented Jan 6, 2026

Thanks a lot for the reasonably fast reply so this did not get shelved again :-D

It should not require any changes on downstream plugins

Great, hoped so. Just the original comment seemed like I could read it several ways :)

So you would Snapshot CertificateCredentialsImpl to say SelfContainedCertificateCredentialsImpl which iteself implements StandardCertificateCredentials

Gotcha, I hope. To be sure I did :) reiterating the plan in my words:

  • Copy and rename CertificateCredentialsImpl Java source to define a new class SelfContainedCertificateCredentialsImpl

    • Can this new class be derived (extends) from CertificateCredentialsImpl and @Override a few methods? Would there be any benefit to that? Or should it be a new implementation from scratch?
  • Fix something... CredentialsProvider.snapshot()?.. to return a SelfContainedCertificateCredentialsImpl given same or another StandardCertificateCredentials implementation on input. Or only CertificateCredentialsImpl whose internals we know and can authoritatively use (and third-party implementations we might not)?

    • I think currently (in this PR) this works via CertificateCredentialsSnapshotTaker removed earlier in plugin history and brought back by the PR. It is registered as an @Extension and the CredentialsProvider.snapshot() method looking for a bestTaker finds it to call for certificate credentials. May/should this solution generally remain, or also needs rework?
  • How should we address de-serialization, e.g. that after a transfer of plaintext keystore through the Channel to a remote agent, the remote JVM would manipulate a safer version of the key store with really encrypted bytes[]?

  • Side note: tests transplanted from this plugin to another plugin (HttpRequestStepCredentialsTest.java in PR linked above) do in fact mention CertificateCredentialsImpl (mostly via CertificateCredentialsImpl.UploadedKeyStoreSource usages to test the scenario, and that sub-class is defined specifically there); I'll check if that can be generalized - but the first question is whether I at all should, given that this bit is only about test code :)

various themes regarding TestExtension

Is that change a "hard requirement" to eventually merge the PR? Would it suffice to just use Devin's tests as imported and augmented in this PR currently, as they seem to already tick most of those points you listed?

This touches on maybe dropping the whole remainder of the CredentialsInPipelineTest file, maybe not. To me it has value as documentation of what does work in pipeline, and keeping such behaviors non-regressed in the long run,

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.

5 participants