Skip to content

Use stdin for supplying auth to CodeQL#1964

Merged
koesie10 merged 3 commits intomainfrom
koesie10/packages-auth
Jan 17, 2023
Merged

Use stdin for supplying auth to CodeQL#1964
koesie10 merged 3 commits intomainfrom
koesie10/packages-auth

Conversation

@koesie10
Copy link
Copy Markdown
Member

This will supply the GitHub access token to certain CodeQL CLI commands such that private packages can be resolved. It will only do so if the user has an existing auth session. If they don't, they will now get a prompt to login. However, this will only happen for commands which actually use authentication, which is limited to packaging commands.

Checklist

  • CHANGELOG.md has been updated to incorporate all user visible changes made by this pull request.
  • Issues have been created for any UI or other user-facing changes made by this pull request.
  • [Maintainers only] If this pull request makes user-facing changes that require documentation changes, open a corresponding docs pull request in the github/codeql repo and add the ready-for-doc-review label there.

This will supply the GitHub access token to certain CodeQL CLI commands
such that private packages can be resolved. It will only do so if the
user has an existing auth session. If they don't, they will now get a
prompt to login. However, this will only happen for commands which
actually use authentication, which is limited to packaging commands.
@koesie10 koesie10 requested a review from a team January 13, 2023 13:08
@koesie10 koesie10 requested a review from a team as a code owner January 13, 2023 13:08
Comment on lines +610 to +612
const accessToken = await credentials.getExistingAccessToken();

const extraArgs = accessToken ? ["--github-auth-stdin"] : [];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why get the accessToken here at all if it's not going to be used below? Should it be the case that if we have an accessToken already, then we use it below and don't prompt?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Though, I wonder if this will be a poor user experience. Most users will only be downloading public packages. They shouldn't need to log in for that.

Do you think it would be better if:

  1. Try to get an existing token.
  2. If found, use that.
  3. If not found, use no token (as before)
  4. If we get an error because the package is private (and no token was provided) prompt the user to log in.
  5. If we get an error because the package is private (and a token was provided) clearly explain that this token doesn't have proper permissions so the user can re-authenticate with a different token.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The only reason for getting the access token here is to check whether the user has an existing access token. Essentially, we're already doing steps 1-3. I think steps 4 and 5 can be implemented separately in the future if private packages are used more widely.

We're not using the access token retrieved here because there can be quite some time between retrieving this access token and the command being run because the command can be queued. By re-retrieving the access token when the CLI actually asks for it, we'll always have an up-to-date access token and don't need to worry about the rare race condition of the user logging out/invalidating their access token while the command is in the queue.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ok. Thanks for the explanation. So, it looks like there are two race conditions that aren't handled:

  1. User logs in after invoking this command, but before the command is run. In this case, the extension will assume that the user is not logged in (this is fine, I think).
  2. User logs out after invoking this command, but before the command is run. In this case, the extension will assume the user is still logged in, try to get the credentials, but credentials.getAccessToken() returns undefined. In this case, will the command hang? Or will it fail since the value undefined is passed to stdin as the string "undefined"?

This race condition is probably rare enough that it's not worth spending too much effort on and when it does happen, it would probably be obvious to the user what happened.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

credentials.getAccessToken() should never return undefined. The difference between getAccessToken and getExistingAccessToken is that getAccessToken will ask the user to login. If the user doesn't login, the promise will reject.

We weren't handling the rejection of the promise and this would permanently hang the CLI server, so I've now pushed a commit that handles this case by giving the accessToken that we retrieved previously. This could be an invalid access token, but should still allow the command to continue.

Comment thread extensions/ql-vscode/src/cli.ts Outdated
progressReporter,
async (line) => {
if (line.startsWith("Enter value for --github-auth-stdin")) {
return credentials.getAccessToken();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this what we want to do?

Suggested change
return credentials.getAccessToken();
return accessToken;

Copy link
Copy Markdown
Contributor

@robertbrignull robertbrignull left a comment

Choose a reason for hiding this comment

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

Code looks ok to me. Code doing this kind of job of starting other processes is always quite complicated.

I'll let @aeisenberg complete his review and approve, but I'm happy whenever he's happy.

Copy link
Copy Markdown
Contributor

@aeisenberg aeisenberg left a comment

Choose a reason for hiding this comment

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

Thanks for the explanation. I think it is good, but I would like to see an updated jsdoc before merging.

Comment on lines +610 to +612
const accessToken = await credentials.getExistingAccessToken();

const extraArgs = accessToken ? ["--github-auth-stdin"] : [];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ok. Thanks for the explanation. So, it looks like there are two race conditions that aren't handled:

  1. User logs in after invoking this command, but before the command is run. In this case, the extension will assume that the user is not logged in (this is fine, I think).
  2. User logs out after invoking this command, but before the command is run. In this case, the extension will assume the user is still logged in, try to get the credentials, but credentials.getAccessToken() returns undefined. In this case, will the command hang? Or will it fail since the value undefined is passed to stdin as the string "undefined"?

This race condition is probably rare enough that it's not worth spending too much effort on and when it does happen, it would probably be obvious to the user what happened.

Comment thread extensions/ql-vscode/src/cli.ts Outdated
Copy link
Copy Markdown
Contributor

@aeisenberg aeisenberg left a comment

Choose a reason for hiding this comment

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

Thanks for the changes. It makes a lot of sense now.

@koesie10 koesie10 merged commit b0168aa into main Jan 17, 2023
@koesie10 koesie10 deleted the koesie10/packages-auth branch January 17, 2023 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants