-
Notifications
You must be signed in to change notification settings - Fork 579
/
Copy pathgithub-app-token.yaml
142 lines (118 loc) · 4.82 KB
/
github-app-token.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
name: github-app-token
labels:
app.kubernetes.io/version: "0.1"
annotations:
tekton.dev/pipelines.minVersion: "0.12.1"
tekton.dev/tags: github
tekton.dev/displayName: "github app token"
spec:
description: >-
Retrive a user token from a GitHub application
This task will get a user token for an installation_id for a GitHub application.
This could be then reuse to do user operations.
workspaces:
- name: secrets
results:
- name: token
description: The user token to use.
params:
- name: installation_id
description: The installation id for the GitHub application to request a token for.
type: string
- name: application_id
description: The application id for the GitHub application to request a token for.
type: string
- name: private_key_path
description: The key path inside the secret workspace
type: string
default: "private.key"
- name: token_expiration_minutes
description: Token expiration time in minutes
type: string
default: "10"
steps:
- name: get-token
image: quay.io/chmouel/github-app-token@sha256:bc45937ae588df876555ebb56c36350ed74592c7f55f2df255cabef39c926a88
env:
- name: GITHUBAPP_KEY_PATH
value: $(workspaces.secrets.path)/$(inputs.params.private_key_path)
- name: GITHUBAPP_APP_ID
value: $(inputs.params.application_id)
- name: GITHUBAPP_INSTALLATION_ID
value: $(inputs.params.installation_id)
- name: GITHUBAPP_TOKEN_EXPIRATION_MINUTES
value: $(inputs.params.token_expiration_minutes)
- name: GITHUBAPP_RESULT_PATH
value: $(results.token.path)
script: |
#!/usr/bin/env python3
import json
import os
import time
import requests
from jwcrypto import jwk, jwt
EXPIRE_MINUTES_AS_SECONDS = int(os.environ.get('GITHUBAPP_TOKEN_EXPIRATION_MINUTES', 10)) * 60
# TODO support github enteprise
GITHUB_API_URL = "https://api.github.com"
class GitHub():
token = None
def __init__(self, private_key, app_id, installation_id=None):
if not isinstance(private_key, bytes):
raise ValueError(f'"{private_key}" parameter must be byte-string')
self._private_key = private_key
self.app_id = app_id
self.token = self._get_token(installation_id)
def _load_private_key(self, pem_key_bytes):
return jwk.JWK.from_pem(pem_key_bytes)
def _app_token(self, expire_in=EXPIRE_MINUTES_AS_SECONDS):
key = self._load_private_key(self._private_key)
now = int(time.time())
token = jwt.JWT(
header={"alg": "RS256"},
claims={
"iat": now,
"exp": now + expire_in,
"iss": self.app_id
},
algs=["RS256"],
)
token.make_signed_token(key)
return token.serialize()
def _get_token(self, installation_id=None):
app_token = self._app_token()
if not installation_id:
return app_token
req = self._request(
"POST",
f"/app/installations/{installation_id}/access_tokens",
headers={
"Authorization": f"Bearer {app_token}",
"Accept": "application/vnd.github.machine-man-preview+json"
})
ret = req.json()
if 'token' not in ret:
raise Exception("Authentication errors")
return ret['token']
def _request(self, method, url, headers={}, data={}):
if self.token and 'Authorization' not in headers:
headers.update({"Authorization": "Bearer " + self.token})
if not url.startswith("http"):
url = f"{GITHUB_API_URL}{url}"
return requests.request(method,
url,
headers=headers,
data=json.dumps(data))
def main():
with open(os.environ['GITHUBAPP_KEY_PATH'], 'rb') as key_file:
key = key_file.read()
github_app = GitHub(
key,
os.environ.get('GITHUBAPP_APP_ID'),
installation_id=os.environ.get('GITHUBAPP_INSTALLATION_ID'))
open(os.environ.get('GITHUBAPP_RESULT_PATH'), 'w').write(github_app.token)
print(github_app.token)
if __name__ == '__main__':
main()