Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
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.
TBH this all seems a bit messy to me.
Why would this just not be in a
SnapshotTakerforGitHubAppCredentials?The refresh can make a call to the controller if on an agent or make a local call if it is on the controller... (then it is just the
DelegatingGitHubAppCredentialscreated by theSnapShotTakerthat needs to have a readResolve to set a channel (but only if used on an agent, and then making a local call if on a controller).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.
hmm I see what you mean. When playing around though, you quickly notice that the
DelegatingGitHubAppCredentialsdoes not extendGitHubAppCredentialsand that's maybe why things started to get messy. It does not seem like you can snapshot aGitHubAppCredentialsto aDelegatingGitHubAppCredentialswith the current design ? Maybe it requires some superclass that hold the "source" for refreshing the token. One source implementation would have appId, privateKey, apiUri and owner and the other the encrypted form of those (whatDelegatingGitHubAppCredentialshas).FYI, my proposed change is to fix the serialization in an upstream implementation. Without changing anything upstream. Maybe we can address the snapshotting problem as part of a different PR. I can create a JENKINS issue for this.
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.
https://issues.jenkins.io/browse/JENKINS-73787
Uh oh!
There was an error while loading. Please reload this page.
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.
snapshot should return (an implementation of) the interface type (because credential types should be written using interfaces as per the design doc) which in this case would be
StandardUsernamePasswordCredentialsso AFAICT without writing code this should be possible.if code really does need a specific type for a GitHubApp credential (which is likely) then the GitHubAppCredential should not be a concrete type but an interface with an implementaion. (doc)
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.
(for the avoidance of doubt I am not blocking this PR, but I do not feel like the addition of debt onto the debt makes me want to approve it either)
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.
No, it is just used as an implementation of
StandardUsernamePasswordCredentialsthat happens to create a “password” on demand.Uh oh!
There was an error while loading. Please reload this page.
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.
TL;DR: Unless I am missing something obvious, this PR seems like the simplest way to fix the issue without causing more problems.
The motivation behind this change is to fix the behavior of a CloudBees-specific subclass of
GitHubAppCredentialsthat comes from a plugin that implements a specialCredentialsProviderthat stores the relevant secrets externally (e.g. the private key). Right now, those credentials may not be used on agents directly.The main problem is that we need multiple levels of dynamic behavior for GitHub app credentials:
ownerviaCredentials.forRunandConnector.lookupScanCredentialsGitHubAppCredentialsright up until the actual password is going to be usedCredentialsSnapshotTakerfor aGitHubAppCredentialsmust translate to a type that is still aGitHubAppCredentials(which is not the case forDelegatingGitHubAppCredentials), otherwiseownerinference totally breaks when credentials are sent from CloudBees CI Operations Center to controllers (this kind of problem was the motivation behind [JENKINS-73388] Allow alternative implementation for GitHub App credentials #796)GitHubAppCredentialswith a type likeDelegatingGitHubAppCredentialswhen serializing the credentials to an agentMaking
writeReplaceprotectedhere allows the CloudBees-specific type to use aCredentialsSnapshotTakerto produce an instance ofGitHubAppCredentialswhere the external secrets have been retrieved, which does not break owner inference for the snapshot, and does not preventDelegatingGitHubAppCredentialsfrom being used for the credentials and the snapshot on agents.If we try to use
CredentialsSnapshotTakerhere and deletewriteReplace, things get more complicated. We need a way to tell in ourCredentialsSnapshotTakerimplementation whether the snapshot is happening because the credentials are being sent to an agent (the only case for OSS Jenkins) or is because the credentials are being sent from OC to controllers (only for CloudBees). This is not just a problem for the specialGitHubAppCredentialssubtype with CloudBees CI, it also applies to usage of plainGitHubAppCredentialsin CloudBees CI (e.g. #616 is somewhat related to this kind of problem). The problem though is thatChannel.current()returnsnullfrom inside ofCredentialsSnapshotTaker.snapshot(at least when checkingtestAgentRefreshhere), so I don't really see any simple way to make this work withoutwriteReplace.Now, are there bigger changes that could be made to avoid this issue? Maybe. For example, if
DelegatingAppCredentialswas itself a subclass ofGitHubAppCredentialsand supported owner inference, then we could always translate directly to it inCredentialsSnapshotTaker. I am not sure if that can be done safely though given the need for agents to be able to refresh the token dynamically. Additionally, the CloudBees-specific subtype ofGitHubAppCredentialscould maybe be deleted with a redesign of the relevant plugin, but we'd still have CloudBees-specific issues with usage of regularGitHubAppCredentialsif we tried to unifyGitHubAppCredentialsSnapshotTakerandGitHubAppCredentials.writeReplace.