Skip to content

Commit 42ebbe0

Browse files
Add new datasource to get GitHub App token (#1671)
* Add new datasource to get GitHub App token * Add new datasource to get GitHub App token * Fix merge error --------- Co-authored-by: Keegan Campbell <[email protected]>
1 parent b0d26d9 commit 42ebbe0

File tree

7 files changed

+195
-0
lines changed

7 files changed

+195
-0
lines changed

examples/app_token/main.tf

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
terraform {
2+
required_providers {
3+
github = {
4+
source = "integrations/github"
5+
}
6+
}
7+
}
8+
9+
provider "github" {}
10+
11+
data "github_app_token" "this" {
12+
app_id = var.app_id
13+
installation_id = var.installation_id
14+
pem_file = file(var.pem_file_path)
15+
}

examples/app_token/variables.tf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
variable "app_id" {
2+
type = string
3+
}
4+
5+
variable "installation_id" {
6+
type = string
7+
}
8+
9+
variable "pem_file_path" {
10+
type = string
11+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package github
2+
3+
import (
4+
"strings"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
7+
)
8+
9+
func dataSourceGithubAppToken() *schema.Resource {
10+
return &schema.Resource{
11+
Read: dataSourceGithubAppTokenRead,
12+
13+
Schema: map[string]*schema.Schema{
14+
"app_id": {
15+
Type: schema.TypeString,
16+
Required: true,
17+
Description: descriptions["app_auth.id"],
18+
},
19+
"installation_id": {
20+
Type: schema.TypeString,
21+
Required: true,
22+
Description: descriptions["app_auth.installation_id"],
23+
},
24+
"pem_file": {
25+
Type: schema.TypeString,
26+
Required: true,
27+
Description: descriptions["app_auth.pem_file"],
28+
},
29+
"token": {
30+
Type: schema.TypeString,
31+
Computed: true,
32+
Sensitive: true,
33+
Description: "The generated token from the credentials.",
34+
},
35+
},
36+
}
37+
}
38+
39+
func dataSourceGithubAppTokenRead(d *schema.ResourceData, meta interface{}) error {
40+
appID := d.Get("app_id").(string)
41+
installationID := d.Get("installation_id").(string)
42+
pemFile := d.Get("pem_file").(string)
43+
44+
baseURL := meta.(*Owner).v3client.BaseURL.String()
45+
46+
// The Go encoding/pem package only decodes PEM formatted blocks
47+
// that contain new lines. Some platforms, like Terraform Cloud,
48+
// do not support new lines within Environment Variables.
49+
// Any occurrence of \n in the `pem_file` argument's value
50+
// (explicit value, or default value taken from
51+
// GITHUB_APP_PEM_FILE Environment Variable) is replaced with an
52+
// actual new line character before decoding.
53+
pemFile = strings.Replace(pemFile, `\n`, "\n", -1)
54+
55+
token, err := GenerateOAuthTokenFromApp(baseURL, appID, installationID, pemFile)
56+
if err != nil {
57+
return err
58+
}
59+
d.Set("token", token)
60+
d.SetId("id")
61+
62+
return nil
63+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package github
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
"os"
8+
"testing"
9+
10+
"github.com/google/go-github/v53/github"
11+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestAccGithubAppTokenDataSource(t *testing.T) {
16+
expectedAccessToken := "W+2e/zjiMTweDAr2b35toCF+h29l7NW92rJIPvFrCJQK"
17+
18+
owner := "test-owner"
19+
20+
pemData, err := os.ReadFile(testGitHubAppPrivateKeyFile)
21+
assert.Nil(t, err)
22+
23+
t.Run("creates a application token without error", func(t *testing.T) {
24+
ts := githubApiMock([]*mockResponse{
25+
{
26+
ExpectedUri: fmt.Sprintf("/api/v3/app/installations/%s/access_tokens", testGitHubAppInstallationID),
27+
ExpectedHeaders: map[string]string{
28+
"Accept": "application/vnd.github.v3+json",
29+
},
30+
ResponseBody: fmt.Sprintf(`{"token": "%s"}`, expectedAccessToken),
31+
StatusCode: 201,
32+
},
33+
})
34+
defer ts.Close()
35+
36+
httpCl := http.DefaultClient
37+
httpCl.Transport = http.DefaultTransport
38+
39+
client := github.NewClient(httpCl)
40+
u, _ := url.Parse(ts.URL + "/")
41+
client.BaseURL = u
42+
43+
meta := &Owner{
44+
name: owner,
45+
v3client: client,
46+
}
47+
48+
testSchema := map[string]*schema.Schema{
49+
"app_id": {Type: schema.TypeString},
50+
"installation_id": {Type: schema.TypeString},
51+
"pem_file": {Type: schema.TypeString},
52+
"token": {Type: schema.TypeString},
53+
}
54+
55+
schema := schema.TestResourceDataRaw(t, testSchema, map[string]interface{}{
56+
"app_id": testGitHubAppID,
57+
"installation_id": testGitHubAppInstallationID,
58+
"pem_file": string(pemData),
59+
"token": "",
60+
})
61+
62+
err := dataSourceGithubAppTokenRead(schema, meta)
63+
assert.Nil(t, err)
64+
assert.Equal(t, expectedAccessToken, schema.Get("token"))
65+
})
66+
}

github/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ func Provider() terraform.ResourceProvider {
167167
"github_actions_secrets": dataSourceGithubActionsSecrets(),
168168
"github_actions_variables": dataSourceGithubActionsVariables(),
169169
"github_app": dataSourceGithubApp(),
170+
"github_app_token": dataSourceGithubAppToken(),
170171
"github_branch": dataSourceGithubBranch(),
171172
"github_branch_protection_rules": dataSourceGithubBranchProtectionRules(),
172173
"github_collaborators": dataSourceGithubCollaborators(),
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
layout: "github"
3+
page_title: "GitHub: github_app_token"
4+
description: |-
5+
Generate a GitHub APP JWT.
6+
---
7+
8+
# github\_app\_token
9+
10+
Use this data source to generate a [GitHub App JWT](https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-json-web-token-jwt-for-a-github-app).
11+
12+
## Example Usage
13+
14+
```hcl
15+
data "github_app_token" "this" {
16+
app_id = "123456"
17+
installation_id = "78910"
18+
pem_file = file("foo/bar.pem")
19+
}
20+
```
21+
22+
## Argument Reference
23+
24+
The following arguments are supported:
25+
26+
* `app_id` - (Required) This is the ID of the GitHub App.
27+
28+
* `installation_id` - (Required) This is the ID of the GitHub App installation.
29+
30+
* `pem_file` - (Required) This is the contents of the GitHub App private key PEM file.
31+
32+
## Attribute Reference
33+
34+
The following additional attributes are exported:
35+
36+
* `token` - The generated GitHub APP JWT.

website/github.erb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@
5252
<li>
5353
<a href="/docs/providers/github/d/app.html">github_app</a>
5454
</li>
55+
<li>
56+
<a href="/docs/providers/github/d/app_token.html"></a>
57+
</li>
5558
<li>
5659
<a href="/docs/providers/github/d/branch.html">github_branch</a>
5760
</li>

0 commit comments

Comments
 (0)