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

GitHub app credentials #971

Merged
merged 7 commits into from
Jun 19, 2020
Merged

GitHub app credentials #971

merged 7 commits into from
Jun 19, 2020

Conversation

unRob
Copy link
Contributor

@unRob unRob commented Apr 3, 2020

Maybe there's something we can do about #418 ? Opening this PR for visibility, hoping to get some feedback on the approach, I'm happy to change directions if someone's got a better idea in mind!


This PR relies on https://github.com/bradleyfalzon/ghinstallation and their dependencies, which might not be fine. At this point its very incomplete, but basically my approach was to expose a few more config values to pass: a github app id, app installation and key (which at this point i had to get myself). These get picked up during server.NewServer and turned into the new type vcs.GithubCredentials (implemented by vcs.GithubUserCredentials and vcs.GithubAppCredentials) before being passed to vcs.NewGithubClient which finally creates the client for those credentials.

Tests were minimally changed to pass, so this is still very much WIP

  • implement the create a github app via manifest workflow
  • implement app callbacks
  • figure out the workflow for creating and persisting private key and installation id
  • figure out how to update ~/.gitconfig credentials before clone with short-lived tokens
  • tests created for new features

If the user doesn't have an app id and private key, the proposed flow is:

  1. Start Atlantis,
  2. Visit atlantis.host/github-app/setup, you're prompted to begin the app creation,
  3. Complete the Github app creation, you're redirected back to Atlantis,
  4. Update config with shown gh-app-id, gh-app-key, and gh-webhook-secret,
  5. Restart Atlantis

Otherwise, it's only steps 4 and 5.

@codecov
Copy link

codecov bot commented Apr 3, 2020

Codecov Report

Merging #971 into master will decrease coverage by 1.17%.
The diff coverage is 46.92%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #971      +/-   ##
==========================================
- Coverage   71.49%   70.31%   -1.18%     
==========================================
  Files          67       69       +2     
  Lines        5564     5778     +214     
==========================================
+ Hits         3978     4063      +85     
- Misses       1272     1388     +116     
- Partials      314      327      +13     
Impacted Files Coverage Δ
server/events/command_runner.go 43.87% <ø> (ø)
server/events/event_parser.go 86.19% <ø> (ø)
server/events_controller.go 57.75% <ø> (ø)
server/github_app_controller.go 0.00% <0.00%> (ø)
server/github_request_validator.go 91.30% <ø> (ø)
server/user_config.go 100.00% <ø> (ø)
server/server.go 59.68% <50.00%> (-2.15%) ⬇️
server/events/working_dir.go 72.26% <57.14%> (-2.02%) ⬇️
cmd/server.go 78.69% <63.63%> (-1.04%) ⬇️
server/events/vcs/github_credentials.go 75.34% <75.34%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 25cd66d...2b74dc9. Read the comment docs.

@donaldpiret
Copy link

@unRob is this functional already? Would love to help test this as GitHub app integration is a blocker for our migration to our new GitHub enterprise setup (service-users are no longer allowed under corp policy and need to be replaced by apps).

@unRob
Copy link
Contributor Author

unRob commented Apr 5, 2020

@donaldpiret It is functional but extremely experimental; I still have to write tests, and would like to setup a terraform test repo and play around before calling this ready. Bear in mind this only implements credentials, and does not go any further in doing fun stuff like posting check comments (see #936) nor automatically registering repositories with Atlantis via webhooks (which I'd love to work on next). Finally, the maintainers have not had a chance yet to send along their feedback, I would not feel comfortable recommending this PR be used in any mission-critical pipelines until they do.

That being said, I've just now made sure the app-creation workflow is functional like so:

# First, run with fake creds and visit http://localhost:4141/github-app/setup
# submit the json payload if it looks good to you (otherwise, lmk what doesn't look right please!)
go run main.go server \
  --log-level debug \
  --repo-whitelist '*' \
  --gh-user fake-user \
  --gh-token fake-token


# Once the app is created, you get returned to your local Atlantis instance and new credentials
# are displayed once. Copy these values to your config and restart Atlantis:
go run main.go server \
  --log-level debug \
  --repo-whitelist '*' \
  --gh-app-id $APP_ID \
  --gh-app-key $PATH_TO_KEY_DOT_PEM \
  --gh-webhook-secret $WEBHOOK_SECRET

Feel free to test it out yourself, and please let me know if you run into trouble. I'll do my best to help debug!

@lkysow
Copy link
Member

lkysow commented Apr 16, 2020

Hey Roberto, sorry for the delay responding. This looks amazing. What can I do to help get this merged? Is the code ready to review and test out yet?

@lkysow lkysow added the feature New functionality/enhancement label Apr 16, 2020
@unRob
Copy link
Contributor Author

unRob commented Apr 16, 2020

@lkysow I'll work this week on adding tests for working_dir and github_client*_test, after which I think it'll be in good shape for a proper review. I've successfully completed app setup (outlined in the comment above) but have yet to test out the rest of the workflow (add repos, make sure clone with temporary tokens works, posting comments, etc). I don't yet have an org to end-to-end test this with, so that's where I could use help.

Code is mostly ready though; I think testing will always reveal some places to improve. Hope that answers your questions, and let me know if there's other considerations I might have missed for seeing this PR through. Thanks!

@unRob
Copy link
Contributor Author

unRob commented Apr 29, 2020

@lkysow I’m starting a job next week and will likely have less time to see this through, could you please review at your earliest convenience? Thanks! Ran e2e tests and addressed some remaining quirks. I’d love some guidance on testing and the way I’ve routed around access tokens.

@unRob
Copy link
Contributor Author

unRob commented Jun 4, 2020

Decided to squash commits since this PR is getting harder to rebase

@lkysow
Copy link
Member

lkysow commented Jun 12, 2020

Got a panic while testign:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x8 pc=0x155f0e4]

goroutine 1 [running]:
github.com/runatlantis/atlantis/server/events/vcs.(*GithubAppCredentials).getInstallationID(0xc000154ec0, 0xc0006be6b0, 0x1094951, 0x1cf57c0)
	/Users/lkysow/go/src/github.com/runatlantis/atlantis/server/events/vcs/github_credentials.go:108 +0xd4
github.com/runatlantis/atlantis/server/events/vcs.(*GithubAppCredentials).transport(0xc000154ec0, 0x1ef91a8, 0x8, 0x2141a80)
	/Users/lkysow/go/src/github.com/runatlantis/atlantis/server/events/vcs/github_credentials.go:136 +0x4d
github.com/runatlantis/atlantis/server/events/vcs.(*GithubAppCredentials).Client(0xc000154ec0, 0x203000, 0x203000, 0x203000)
	/Users/lkysow/go/src/github.com/runatlantis/atlantis/server/events/vcs/github_credentials.go:78 +0x2f
github.com/runatlantis/atlantis/server/events/vcs.NewGithubClient(0x1ea2a79, 0xa, 0x2124b40, 0xc000154ec0, 0xc000518c80, 0xc000139d60, 0x0, 0x1)
	/Users/lkysow/go/src/github.com/runatlantis/atlantis/server/events/vcs/github_client.go:60 +0x4c
github.com/runatlantis/atlantis/server.NewServer(0x0, 0xc0005feb70, 0x25, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)

Looks like I still have to pass atlantis server --gh-user fake --gh-token fake

@unRob
Copy link
Contributor Author

unRob commented Jun 17, 2020

Thanks for the report!

I tried a few things to replicate but could not reproduce the panic you posted, including:

  • passing no arguments (got Error: --gh-user/--gh-token or --gh-app-id/--gh-app-key or --gitlab-user/--gitlab-token or --bitbucket-user/--bitbucket-token or --azuredevops-user/--azuredevops-token must be set),
  • initializing without installing (got Error: initializing server: Error initializing github authentication transport: wrong number of installations, expected 1, found 0), and,
  • passing both (no error, token is selected over app auth).

I did, however, notice that the token was useless because I was still relying on per-repo webhooks, so I addressed that by activating the app-wide Webhook and listening to issue_comment, (among others recommended by runatlantis.io/docs/configuring-webhooks.md which I updated as well).

Could you help me with a little more context to reproduce the panic? I ran the whole workflow on macOS like so:

git reset --hard origin/feature/github-app-credentials
go build
./atlantis server \
  --gh-user very-fake-username --gh-token super-fake-token \
  --log-level debug --repo-whitelist '*'
# then I go to hosts-ip:4141/github-app/setup, click continue and get redirected back
# followed the link to install the app, then
^C
pbpaste > key.pem
./atlantis server \
  --gh-app-id 69100 --gh-webhook-secret "some-secret" --gh-app-key key.pem \
  --log-level debug --repo-whitelist '*'

In running these again, I noticed a probable cause for that panic: not passing in a key file (or otherwise having problems initializing ghinstallation.NewAppsTransportKeyFromFile. So scratch all of the above, good thing I also addressed docs.

// GithubAppWorkingDir implements WorkingDir.
// It acts as a proxy to an instance of WorkingDir that refreshes the app's token
// before every clone, given Github App tokens expire quickly
type GithubAppWorkingDir struct {
Copy link
Member

Choose a reason for hiding this comment

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

Really awesome how clean this is.

DataDir: userConfig.DataDir,
CheckoutMerge: userConfig.CheckoutStrategy == "merge",
}
// provide fresh tokens before clone from the GitHub Apps integration, proxy workingDir
if githubAppEnabled {
if !userConfig.WriteGitCreds {
Copy link
Member

Choose a reason for hiding this comment

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

I've changed this in my branch and instead will require users to set --write-git-creds. I didn't want to assume users wanted that file written, especially because it clobbers the old file. I've also changed that a bit in my branch so it just replaces the line that needs replacing.

@lkysow lkysow mentioned this pull request Jun 19, 2020
@lkysow lkysow merged commit 2b74dc9 into runatlantis:master Jun 19, 2020
@lkysow
Copy link
Member

lkysow commented Jun 19, 2020

This will be in the next Atlantis release. Amazing work!!! 🎉 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New functionality/enhancement
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants