From 4eb97dead9473866ff2dcca9f5461789e8aea64a Mon Sep 17 00:00:00 2001 From: Marc-Antoine Godde Date: Wed, 10 Jan 2024 14:16:43 +0100 Subject: [PATCH] Use GitHub app for the PR/MR workflow (#199) * feat(github): replace github pat by a github app Remove the GitHub PAT authentication scheme by a proper Github app * docs(github): add github app documentation Add the required documentation to configure the Github App for the PR/MR workflow * docs(github): add badge information Add link to configure a badge for the Github App * test(github): fix test Add missing variables in test data * fix(github): add missing variables * feat(revert): add apitoken config * feat(revert): add github token support * docs(github): add api token doc --- deploy/charts/burrito/values.yaml | 6 + docs/assets/pr-mr-workflow/github_app_id.png | Bin 0 -> 31359 bytes .../pr-mr-workflow/github_installation_id.png | Bin 0 -> 37602 bytes docs/operator-manual/pr-mr-workflow.md | 157 +++++++++++++++++- go.mod | 3 + go.sum | 6 + internal/burrito/config/config.go | 5 +- internal/burrito/config/config_test.go | 13 +- .../config/testdata/test-config-1.yaml | 3 + .../terraformpullrequest/github/provider.go | 39 +++-- 10 files changed, 209 insertions(+), 23 deletions(-) create mode 100644 docs/assets/pr-mr-workflow/github_app_id.png create mode 100644 docs/assets/pr-mr-workflow/github_installation_id.png diff --git a/deploy/charts/burrito/values.yaml b/deploy/charts/burrito/values.yaml index f8a704ec..fa4b0a59 100644 --- a/deploy/charts/burrito/values.yaml +++ b/deploy/charts/burrito/values.yaml @@ -39,6 +39,12 @@ config: healthProbeBindAddress: ":8081" kubernetesWebhookPort: 9443 githubConfig: + # -- Prefer override with the BURRITO_CONTROLLER_GITHUBCONFIG_APPID environment variable + appId: "" + # -- Prefer override with the BURRITO_CONTROLLER_GITHUBCONFIG_INSTALLATIONID environment variable + installationId: "" + # -- Prefer override with the BURRITO_CONTROLLER_GITHUBCONFIG_PRIVATEKEY environment variable + privateKey: "" # -- Prefer override with the BURRITO_CONTROLLER_GITHUBCONFIG_APITOKEN environment variable apiToken: "" gitlabConfig: diff --git a/docs/assets/pr-mr-workflow/github_app_id.png b/docs/assets/pr-mr-workflow/github_app_id.png new file mode 100644 index 0000000000000000000000000000000000000000..db579190bd5c9476bf289dc51087f35aef1a356c GIT binary patch literal 31359 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 literal 0 HcmV?d00001 diff --git a/docs/assets/pr-mr-workflow/github_installation_id.png b/docs/assets/pr-mr-workflow/github_installation_id.png new file mode 100644 index 0000000000000000000000000000000000000000..df0e34d5377de00266b7c6b45949339264698307 GIT binary patch literal 37602 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

!!! info - In this documentation all references to pull requests can be change to merge requests for GitLab. However, the resulting Kubernetes object will still be named `TerraformPullRequest`. +In this documentation all references to pull requests can be change to merge requests for GitLab. However, the resulting Kubernetes object will still be named `TerraformPullRequest`. ## Components ### The server !!! info - For more information about the server, see the [architectural overview](./architecture.md) documentation. +For more information about the server, see the [architectural overview](./architecture.md) documentation. Upon receiving a Pull Request creation event, the server creates a `TerraformPullRequest` resource. @@ -35,18 +35,157 @@ The status of a `TerraformPulLRequest` is defined using the [conditions standard - `IsCommentUpToDate`. This condition is used to check if the controller needs to send a comment to a pull request. This is checked by comparing the last discovered commit and the last commit for which a comment was already sent. !!! info - We use annotations to store information. +We use annotations to store information. With those 3 conditions, we defined 3 states: - `Idle`. This is the state of a pull request if nothing needs to be done. - `DiscoveryNeeded`. This is the state of a pull request if the controller needs to check which layers are affected on the given pull request. -- `CommentNeeded`. This is the state of a pull request if the controller needs to send a comment to the git provider's API. +- `CommentNeeded`. This is the state of a pull request if the controller needs to send a comment to the git provider's API. ## Configuration -| Environment variable | Description | -| :----------------------------------------: | :-------------------------------------------: | -| `BURRITO_CONTROLLER_GITHUBCONFIG_APITOKEN` | the API token to send comment to GitHub's API | -| `BURRITO_CONTROLLER_GITLABCONFIG_APITOKEN` | the API token to send comment to GitLab's API | -| `BURRITO_CONTROLLER_GITLABCONFIG_URL` | the URL of the GitLab instance | +### GitHub with a dedicated GitHub App + +#### Create the GitHub App + +You can create and register GitHub Apps in your personal GitHub account or in any GitHub organization where you have administrative access. + +Follow the instructions in the GitHub documentation on [Creating a GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app). Populate the settings as follows: + +- **GitHub App Name**: Choose a name for your GitHub App. For example, something featuring `burrito`. +- **Homepage URL**: Enter https://padok-team.github.io/burrito. +- **Webhook**: Deselect Active. The app doesn't use this webhook events mechanism at the moment. +- **Permissions**: Configure the following **Repository Permissions**. + - **Metadata**: Select Read-only. + - **Pull requests**: Select Read & write. This is required to issue comments on pull requests. +- Where can this GitHub App be installed: Select **Any account**. + +#### Creating a custom badge for your GitHub App + +You can create a custom badge for your GitHub App to display on your GitHub repository. Follow the instructions in the GitHub documentation on [Creating a custom badge for your GitHub App](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/creating-a-custom-badge-for-your-github-app). + +We suggest using the following one: + +

+ +#### Install the GitHub App + +Follow the instructions in the GitHub documentation on [Installing your own GitHub App](https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app), and note the following: + +- For Repository access, select **Only select repositories**, and then select the repos you want to connect with Burrito. + +#### Get the Installation ID and App ID + +You need the **Installation ID** and **App ID** to configure Burrito. + +1. Get the **Installation ID** from the URL of the installed app, such as: + +

+ +2. Get the **App ID** from the app's General tab. + +

+ +#### Generate a private key + +You need a private key for your GitHub app to configure Burrito. + +- Follow the instructions in the GitHub documentation for [generating private keys for GitHub Apps](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/managing-private-keys-for-github-apps#generating-private-keys) + +- Save the private key file to your local machine. GitHub only stores the public portion of the key. + +#### Configure Burrito + +Add the following environment variables to your Burrito controller deployment: + +- `BURRITO_CONTROLLER_GITHUBCONFIG_APPID`: The App ID of your GitHub app. +- `BURRITO_CONTROLLER_GITHUBCONFIG_INSTALLATIONID`: The Installation ID of your GitHub app. +- `BURRITO_CONTROLLER_GITHUBCONFIG_PRIVATEKEY`: The private key of your GitHub app. + +For example: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: burrito-github-config + namespace: burrito +type: Opaque +stringData: + BURRITO_CONTROLLER_GITHUBCONFIG_APPID: "123456" + BURRITO_CONTROLLER_GITHUBCONFIG_INSTALLATIONID: "12345678" + BURRITO_CONTROLLER_GITHUBCONFIG_PRIVATEKEY: | + -----BEGIN RSA PRIVATE KEY----- + ... + -----END RSA PRIVATE KEY----- +``` + +### GitHub with a personal access token + +#### Generate a personal access token + +You need a personal access token to configure Burrito. You can generate a personal access token in your GitHub account. + +Follow the instructions in the GitHub documentation for [creating a personal access token](https://docs.github.com/en/github/authenticating-to-github/creating-a-personal-access-token): + +- It should be a **fine-grained token**. +- **Permissions**: Configure the following **Repository Permissions**. + - **Metadata**: Select Read-only. + - **Pull requests**: Select Read & write. This is required to issue comments on pull requests. +- Under **Repository access**, select which repositories you want the token to access. + +#### Configure Burrito + +Add the following environment variables to your Burrito controller deployment: + +- `BURRITO_CONTROLLER_GITHUBCONFIG_APITOKEN`: The personal access token of your GitHub app. + +For example: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: burrito-github-config + namespace: burrito +type: Opaque +stringData: + BURRITO_CONTROLLER_GITHUBCONFIG_APITOKEN: github_pat_123456 +``` + +### GitLab + +#### Generate a private token + +You need a private token for your GitLab app to configure Burrito. You can generate a private token in your GitLab account. Follow the instructions in the GitLab documentation for [generating a private token](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#creating-a-personal-access-token). + +#### Configure Burrito + +Add the following environment variables to your Burrito controller deployment: + +- `BURRITO_CONTROLLER_GITLABCONFIG_APITOKEN`: The private token of your GitLab app. +- `BURRITO_CONTROLLER_GITLABCONFIG_URL`: The URL of your GitLab instance. + +For example: + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: burrito-gitlab-config + namespace: burrito +type: Opaque +stringData: + BURRITO_CONTROLLER_GITLABCONFIG_APITOKEN: "123456" + BURRITO_CONTROLLER_GITLABCONFIG_URL: "https://gitlab.example.com" +``` + +| Environment variable | Description | +| :----------------------------------------------: | :--------------------------------------------------------: | +| `BURRITO_CONTROLLER_GITHUBCONFIG_APPID` | the GtiHub App ID to send comment to GitHub's API | +| `BURRITO_CONTROLLER_GITHUBCONFIG_INSTALLATIONID` | the GitHub Installation ID to send comment to GitHub's API | +| `BURRITO_CONTROLLER_GITHUBCONFIG_PRIVATEKEY` | the GitHub App private key to send comment to GitHub's API | +| `BURRITO_CONTROLLER_GITHUBCONFIG_APITOKEN` | the API token to send comment to GitHub's API | +| `BURRITO_CONTROLLER_GITLABCONFIG_APITOKEN` | the API token to send comment to GitLab's API | +| `BURRITO_CONTROLLER_GITLABCONFIG_URL` | the URL of the GitLab instance | diff --git a/go.mod b/go.mod index 935f8f7e..7f9b2618 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/padok-team/burrito go 1.19 require ( + github.com/bradleyfalzon/ghinstallation/v2 v2.8.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/terraform-json v0.17.1 github.com/onsi/ginkgo/v2 v2.13.1 @@ -28,7 +29,9 @@ require ( github.com/go-git/go-billy/v5 v5.5.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-github/v56 v56.0.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect diff --git a/go.sum b/go.sum index 478f05e1..61baf1f0 100644 --- a/go.sum +++ b/go.sum @@ -59,6 +59,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bombsimon/logrusr/v4 v4.0.0 h1:Pm0InGphX0wMhPqC02t31onlq9OVyJ98eP/Vh63t1Oo= github.com/bombsimon/logrusr/v4 v4.0.0/go.mod h1:pjfHC5e59CvjTBIU3V3sGhFWFAnsnhOR03TRc6im0l8= +github.com/bradleyfalzon/ghinstallation/v2 v2.8.0 h1:yUmoVv70H3J4UOqxqsee39+KlXxNEDfTbAp8c/qULKk= +github.com/bradleyfalzon/ghinstallation/v2 v2.8.0/go.mod h1:fmPmvCiBWhJla3zDv9ZTQSZc8AbwyRnGW1yg5ep1Pcs= github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -133,6 +135,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -184,6 +188,8 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk= github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= +github.com/google/go-github/v56 v56.0.0 h1:TysL7dMa/r7wsQi44BjqlwaHvwlFlqkK8CtBWCX3gb4= +github.com/google/go-github/v56 v56.0.0/go.mod h1:D8cdcX98YWJvi7TLo7zM4/h8ZTx6u6fwGEkCdisopo0= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= diff --git a/internal/burrito/config/config.go b/internal/burrito/config/config.go index eed36e0b..1b2871a6 100644 --- a/internal/burrito/config/config.go +++ b/internal/burrito/config/config.go @@ -45,7 +45,10 @@ type ControllerConfig struct { } type GithubConfig struct { - APIToken string `mapstructure:"apiToken"` + AppId int64 `mapstructure:"appId"` + InstallationId int64 `mapstructure:"installationId"` + PrivateKey string `mapstructure:"privateKey"` + APIToken string `mapstructure:"apiToken"` } type GitlabConfig struct { diff --git a/internal/burrito/config/config_test.go b/internal/burrito/config/config_test.go index 61b08feb..7d38e9b3 100644 --- a/internal/burrito/config/config_test.go +++ b/internal/burrito/config/config_test.go @@ -69,7 +69,10 @@ func TestConfig_FromYamlFile(t *testing.T) { HealthProbeBindAddress: ":8081", KubernetesWebhookPort: 9443, GithubConfig: config.GithubConfig{ - APIToken: "github-token", + AppId: 123456, + InstallationId: 12345678, + PrivateKey: "private-key", + APIToken: "github-token", }, GitlabConfig: config.GitlabConfig{ APIToken: "gitlab-token", @@ -146,6 +149,9 @@ func TestConfig_EnvVarOverrides(t *testing.T) { setEnvVar(t, "BURRITO_CONTROLLER_TIMERS_FAILUREGRACEPERIOD", "1m", &envVarList) setEnvVar(t, "BURRITO_CONTROLLER_TERRAFORMMAXRETRIES", "32", &envVarList) setEnvVar(t, "BURRITO_CONTROLLER_LEADERELECTION_ID", "other-leader-id", &envVarList) + setEnvVar(t, "BURRITO_CONTROLLER_GITHUBCONFIG_APPID", "123456", &envVarList) + setEnvVar(t, "BURRITO_CONTROLLER_GITHUBCONFIG_INSTALLATIONID", "12345678", &envVarList) + setEnvVar(t, "BURRITO_CONTROLLER_GITHUBCONFIG_PRIVATEKEY", "private-key", &envVarList) setEnvVar(t, "BURRITO_CONTROLLER_GITHUBCONFIG_APITOKEN", "pr-github-token", &envVarList) setEnvVar(t, "BURRITO_CONTROLLER_GITLABCONFIG_APITOKEN", "mr-gitlab-token", &envVarList) setEnvVar(t, "BURRITO_CONTROLLER_GITLABCONFIG_URL", "https://gitlab.com", &envVarList) @@ -204,7 +210,10 @@ func TestConfig_EnvVarOverrides(t *testing.T) { HealthProbeBindAddress: ":8081", KubernetesWebhookPort: 9443, GithubConfig: config.GithubConfig{ - APIToken: "pr-github-token", + AppId: 123456, + InstallationId: 12345678, + PrivateKey: "private-key", + APIToken: "pr-github-token", }, GitlabConfig: config.GitlabConfig{ APIToken: "mr-gitlab-token", diff --git a/internal/burrito/config/testdata/test-config-1.yaml b/internal/burrito/config/testdata/test-config-1.yaml index 4472a780..d8b6310e 100644 --- a/internal/burrito/config/testdata/test-config-1.yaml +++ b/internal/burrito/config/testdata/test-config-1.yaml @@ -27,6 +27,9 @@ controller: healthProbeBindAddress: ":8081" kubernetesWebhookPort: 9443 githubConfig: + appId: 123456 + installationId: 12345678 + privateKey: "private-key" apiToken: "github-token" gitlabConfig: apiToken: "gitlab-token" diff --git a/internal/controllers/terraformpullrequest/github/provider.go b/internal/controllers/terraformpullrequest/github/provider.go index 9a6c8847..2a8e6ccd 100644 --- a/internal/controllers/terraformpullrequest/github/provider.go +++ b/internal/controllers/terraformpullrequest/github/provider.go @@ -3,9 +3,11 @@ package github import ( "context" "errors" + "net/http" "strconv" "strings" + "github.com/bradleyfalzon/ghinstallation/v2" "github.com/google/go-github/v50/github" configv1alpha1 "github.com/padok-team/burrito/api/v1alpha1" "github.com/padok-team/burrito/internal/annotations" @@ -20,22 +22,37 @@ type Github struct { *github.Client } -func (g *Github) IsConfigPresent(c *config.Config) bool { - return c.Controller.GithubConfig.APIToken != "" +func (g *Github) IsAppConfigPresent(c *config.Config) bool { + return c.Controller.GithubConfig.AppId != 0 && c.Controller.GithubConfig.InstallationId != 0 && len(c.Controller.GithubConfig.PrivateKey) != 0 +} + +func (g *Github) IsAPITokenConfigPresent(c *config.Config) bool { + return len(c.Controller.GithubConfig.APIToken) != 0 } func (g *Github) Init(c *config.Config) error { - ctx := context.Background() - if !g.IsConfigPresent(c) { + if g.IsAppConfigPresent(c) { + itr, err := ghinstallation.New(http.DefaultTransport, c.Controller.GithubConfig.AppId, c.Controller.GithubConfig.InstallationId, []byte(c.Controller.GithubConfig.PrivateKey)) + + if err != nil { + return errors.New("error while creating github installation client: " + err.Error()) + } + + g.Client = github.NewClient(&http.Client{Transport: itr}) + return nil + } else if g.IsAPITokenConfigPresent(c) { + ctx := context.Background() + + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: c.Controller.GithubConfig.APIToken}, + ) + tc := oauth2.NewClient(ctx, ts) + + g.Client = github.NewClient(tc) + return nil + } else { return errors.New("github config is not present") } - ts := oauth2.StaticTokenSource( - &oauth2.Token{AccessToken: c.Controller.GithubConfig.APIToken}, - ) - tc := oauth2.NewClient(ctx, ts) - - g.Client = github.NewClient(tc) - return nil } func (g *Github) IsFromProvider(pr *configv1alpha1.TerraformPullRequest) bool {