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

[JENKINS-69488] do not SnapShot GitHubAppCredentials #616

Merged
merged 6 commits into from Sep 6, 2022

Conversation

jtnord
Copy link
Member

@jtnord jtnord commented Sep 1, 2022

The GitHubApp Credentials converts itself when serialized over remoting
to a DelegatingGitHubAppCredentials to support token refresh.

Whilst it would naively be trivial to replace this with an
implenentation in the GitHubAppCredentialsSnapshotTaker that did the
conversion, this causes issues in controller to controller propagation.

When a Snapshot is taken there may or may not be a Channel in place,
however this does not detract from the fact that it is done so
credentials can be held complete
The code could be obtaining the credentials to send to some code but may
be doing it in outside of a specific task (th a remoting channel (e.g. snapshot a credential, then
obtain a channel from a computer to execute some code). Whilst unlikely
for this specific credential type - it is also a very generic type and
nothing would prevent code from doing this - nor would that code be
incorrect.

This change purely goes back to the status quo before jenkinsci/credentials-plugin#327 was introduced.

Description

A brief summary describing the changes in this pull request. See
JENKINS-69488 for further information.

required due to jenkinsci/credentials-plugin#327 see also #336 #334

Submitter checklist

  • Link to JIRA ticket in description, if appropriate.
  • Change is code complete and matches issue description
  • Automated tests have been added to exercise the changes
  • Reviewer's manual test instructions provided in PR description. See Reviewer's first task below.

Reviewer checklist

  • Run the changes and verify that the change matches the issue description
  • Reviewed the code
  • Verified that the appropriate tests have been written or valid explanation given

Documentation changes

  • Link to jenkins.io PR, or an explanation for why no doc changes are needed

Users/aliases to notify

The GitHubApp Credentials converts itself when serialized over remoting
to a DelegatingGitHubAppCredentials to support token refresh.

Whilst it would naively be trivial to replace this with an
implenentation in the GitHubAppCredentialsSnapshotTaker that did the
conversion, this causes issues in controller to controller propagation.

When a Snapshot is taken there may or may not be a Channel in place,
however this does not detract from the fact that it is done so
credentials can be held complete
The code could be obtaining the credentials to send to some code but may
be doing it in outside of a specific task (th a remoting channel (e.g. snapshot a credential, then
obtain a channel from a computer to execute some code).  Whilst unlikely
for this specific credential type - it is also a very generic type and
nothing would prevent code from doing this - nor would that code be
incorrect.
@jtnord jtnord requested review from jglick and a team September 1, 2022 12:55
@jglick jglick added the bug label Sep 1, 2022
@jglick
Copy link
Member

jglick commented Sep 1, 2022

testAgentRefresh failing.

Copy link
Member

@jglick jglick left a comment

Choose a reason for hiding this comment

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

Seems safe enough for a hotfix, though I recommend removing the writeReplace so that only CredentialsProvider.snapshot (typically called from git-client IIRC) will activate the special behavior.

@jtnord
Copy link
Member Author

jtnord commented Sep 1, 2022

testAgentRefresh

I think this is the same flaky test @olamy was trying to track down in https://github.com/jenkinsci/github-branch-source-plugin/pull/609/checks?check_run_id=7918023888 ?

@jtnord
Copy link
Member Author

jtnord commented Sep 1, 2022

possibly not flaky - failed twice locally, reset to master and it passed twice in a row...

@jtnord jtnord disabled auto-merge September 1, 2022 15:01
Comment on lines 466 to 464
"Generating App Installation Token for app ID 54321", // 1
"Generating App Installation Token for app ID 54321", // 2
"Failed to generate new GitHub App Installation Token for app ID 54321: cached token is stale but has not expired", // 3
"Generating App Installation Token for app ID 54321 on agent", // 1
"Failed to generate new GitHub App Installation Token for app ID 54321 on agent: cached token is stale but has not expired", // 2
"Generating App Installation Token for app ID 54321 on agent", // 3
Copy link
Member

Choose a reason for hiding this comment

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

Why is this happening? The tokens are supposed to be generated on the controller, not the agent.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

@jtnord jtnord Sep 2, 2022

Choose a reason for hiding this comment

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

the logs are logs of both the agent and the controller - so the token should be "generated" on the agent (but it is not generated there - it is just asking the controller).

Level.FINE, "Generating App Installation Token for app ID {0} on agent", appID);

The order here is messed up - the logs are "all the agent logs" then "all the controller logs". that really confused me at first and I am fixing that now so the logs will always be in the correct order. (which is why I have not yet enabled auto merge)

#609 fixed the test (but left the bug) - because the Delegated credential was no longer sent to the agent (as it was Snapshotted and converted to a basic username password) and so it never refreshed on the agent as it never existed there.

Copy link
Member Author

Choose a reason for hiding this comment

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

should be a bit more cleaner now in 751a870

@jtnord
Copy link
Member Author

jtnord commented Sep 2, 2022

I have run the test locally with both java8 and java11 (windows) where it had appeared to be flaky previously. it did not fail locally for me. There is now more logging should it become flaky or the CI fails.

WorkflowRun run = job.scheduleBuild2(0).waitForStart();
r.waitUntilNoActivity();

System.out.println(JenkinsRule.getLog(run));
Copy link
Member Author

Choose a reason for hiding this comment

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

replaced by the BuildWatcher.

Comment on lines +138 to +139
// but even though we can not capture the logs we want to echo them
r.showAgentLogs(agent, loggerRule);
Copy link
Member

Choose a reason for hiding this comment

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

Could probably rework showAgentLogs to mirror messages to the controller with a prefix or whatever.

Copy link
Member Author

@jtnord jtnord Sep 2, 2022

Choose a reason for hiding this comment

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

Not sure I understand.
Do you mean set a formatter here that prepends "$agentName"?

In which case something for JTH outside of the scope here?

Copy link
Member

Choose a reason for hiding this comment

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

something for JTH

Right.

outside of the scope here

Well, except insofar as it would be handy to pick up here.

Copy link
Member Author

@jtnord jtnord Sep 5, 2022

Choose a reason for hiding this comment

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

the logs already contain the agent name., slave0 in the below example

61.145 [test-creds #1] using credential myAppCredentialsId
61.145 [test-creds #1] Fetching changes from the remote Git repository
61.206 [slave0] [id=211]	FINE	o.j.p.g.GitHubAppCredentials$DelegatingGitHubAppCredentials#getPassword: Generating App Installation Token for app ID 54321 on agent
61.207 [id=102]	FINE	o.j.p.g.GitHubAppCredentials$DelegatingGitHubAppCredentials$GetToken#call: Generating App Installation Token for app ID 54321 for agent
61.403 [test-creds #1] Checking out Revision a9cd113a37fe363bc18dc40ac3bb1024bbc62842 (refs/remotes/origin/master)
61.558 [test-creds #1] Commit message: "init"
61.578 [id=181]	FINE	o.j.p.g.GitHubAppCredentials#getToken: Generating App Installation Token for app ID 54321

So I'm no longer clear what is being asked here @jglick

showAgentLogs -> publish

Copy link
Member Author

Choose a reason for hiding this comment

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

perhaps it is the comment that is missleading. it is in reference to the comment on the LoggerRule

// here to aid debugging - we can not use LoggerRule for the test assertion as it only captures
// logs from the controller
@ClassRule
public static LoggerRule loggerRule =
new LoggerRule().record(GitHubAppCredentials.class, Level.FINE);

Comment on lines -314 to +326
long notStaleSeconds = GitHubAppCredentials.AppInstallationToken.NOT_STALE_MINIMUM_SECONDS;
final long notStaleSeconds =
GitHubAppCredentials.AppInstallationToken.NOT_STALE_MINIMUM_SECONDS;
Copy link
Member

Choose a reason for hiding this comment

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

No-op?

Copy link
Member Author

@jtnord jtnord Sep 2, 2022

Choose a reason for hiding this comment

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

Used in the finally block which is untouched so not in the diff.

} finally {
GitHubAppCredentials.AppInstallationToken.NOT_STALE_MINIMUM_SECONDS = notStaleSeconds;
logRecorder.doClear();
}

Made it final to avoid it being changed accidentally..

Probably should use a FlagRule but probably best left for a larger cleanup

Comment on lines -398 to +406
long notStaleSeconds = GitHubAppCredentials.AppInstallationToken.NOT_STALE_MINIMUM_SECONDS;
final long notStaleSeconds =
GitHubAppCredentials.AppInstallationToken.NOT_STALE_MINIMUM_SECONDS;
Copy link
Member

Choose a reason for hiding this comment

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

ditto

Comment on lines -465 to +482
// (agent log added out of order, see below)
"Generating App Installation Token for app ID 54321", // 1
"Generating App Installation Token for app ID 54321", // 2
"Failed to generate new GitHub App Installation Token for app ID 54321: cached token is stale but has not expired", // 3
// node ('my-agent') {
// checkout scm
// checkout scm
// echo 'First Checkout on agent should use cached token passed via remoting'
// git url: REPO, credentialsId: 'myAppCredentialsId'
"Generating App Installation Token for app ID 54321",
// echo 'Multiple checkouts in quick succession should use cached token'
// git ....
// (No token generation)
// sleep
// echo 'Checkout after token is stale refreshes via remoting - fallback due to
// unexpired token'
// git ....
Copy link
Member

Choose a reason for hiding this comment

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

Is there a diff link to the pre-#609 state for ease of review?

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Thanks. I guess the non-obvious parts of the test diff are due to the addition of chronological sorting.

Copy link
Member Author

Choose a reason for hiding this comment

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

yup. those where already commented inline (but the message may have changed slightly

…bAppCredentialsTest.java

Co-authored-by: Jesse Glick <jglick@cloudbees.com>
@jglick
Copy link
Member

jglick commented Sep 6, 2022

Fine for me; let me know if and when you want this merged & released.

@jtnord jtnord merged commit d46793a into jenkinsci:master Sep 6, 2022
@jtnord jtnord deleted the JENKINS-69488 branch September 6, 2022 16:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
3 participants