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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
|
# Thinking Out Loud
## Enforcing authz
Give me a token with these claims:
```json
{
"iss": "authz.hashicorp.com",
"sub": "id", <- id of the user, team, organization
"aud": "app.terraform.io",
"exp": "unix-timestamp",
"nbf": "unix-timestamp",
"iat": "unix-timestamp",
"jti": "token id generated by issuer",
"scope": "terraform.teams.create, terraform.teams.read", // how do we scope this to each organization?
}
```
## Example List teams
GET /api/v2/org/:org_id/teams
Host: app.terraform.io
Authorization: Bearer my.jwt.token
* authz:
* find user, team, or org record. how do we know which type to load?
* POST /tokens/
Host: authz.hashicorp.com
{
"token": "my.jwt.token"
}
200 OK
{
sub: "id", <- id of the user, team, organization
scope: "terraform.teams.create, terraform.teams.read", // how do we scope this to each organization?
}
## Managing authz
*
## TFC
1. User-Agent goes to https://app.terraform.io/items/
2. app.terraform.io redirects User-Agent to https://idp.terraform.io
3. user enters credentials
4. idp determines grant type to respond with (e.g. authorization code grant, saml bearer token grant, openid ref token, openid identity token)
5. idp redirects/posts to resource server (https://app.terraform.io) with grant.
6. resource server (https://app.terraform.io) converts grant to access token.
7. redirect to https://app.terraform.io/items/
8. browser presents access token with JWT claims.
9. resource server verifies claims in the token and determines if subject has access to the resource.
## TFE
1. User-Agent goes to https://app.terraform.internal/items/
2. app.terraform.internal redirects User-Agent to https://idp.terraform.internal (alias for app.terraform.internal or external idp that support OpenID Connect)
3. user enters credentials
4. idp determines grant type to respond with (e.g. authorization code grant, saml bearer token grant, openid ref token, openid identity token)
5. idp redirects/posts to resource server (https://app.terraform.internal) with grant.
6. resource server (https://app.terraform.internal) converts grant to access token.
7. redirect to https://app.terraform.internal/items/
8. browser presents access token with JWT claims.
9. resource server verifies claims in the token and determines if subject has access to the resource.
```plaintext
| -------------------
| |->| gRPC Gateway |
| | -------------------
| | |
--------- --------- | ------------------ | --------v----------
|AWS ALB| ->|Traefik|---->| consul service | -- | gRPC Public API |
--------- --------- | ------------------ -------------------
| |
| --------v----------
| | gRPC Private API |
| _-------------------
|
-----------------------------------
| 1. RBAC: is request allowed? |
| 1. Billing: is request allowed? |
| 1. Access resource |
| 1. Record event for auditing |
-----------------------------------
```
```
---------------------
|-->| Service Principals |
| ---------------------
|
---------------- | ---------
| Organization | ----->| Users |
---------------- | ---------
| |
| | ----------
| |-->| Groups |
| ----------
|
|
|
|----------------|--------------------|
| | |
------------- ------------- ------------
| Project 1 | | Project 2 | | Folder A |
------------- ------------- ------------
| |
------------- -------------
| Project 3 | | Project 4 |
------------- -------------
Permissions:
* `consul.cluster.create`
* `consul.cluster.get`
* `consul.cluster.delete`
Roles:
* Permissions: [ consul.cluster.create, consul.cluster.get, consul.cluster.delete ]
Bindings:
* Principal, Permissions, Level
{
role: "role/admin",
principals: [
"group/managers",
"user/123",
"service_principal/456"
]
}
```
```
{
"organization_id": 123,
"project_id": 456,
"required_permission": "consul.cluster.create",
}
```
Hashicorp (PKI)
```plaintext
--------------------
| Let's Encrypt CA |
--------------------
|
| issues
----------------------
| Let's Encrypt Cert |
----------------------
?
---------------------
| HashiCorp Root CA |
---------------------
|
| signs
|
---v---------------------------------------------
| HashiCorp Primary Intermediate CA (HC 101 CA) |
-------------------------------------------------
|
---v--------------------
| Vault: Data-Plane CA |
------------------------
| signs
|----------------------------------------
| |
---v--------------------------- -------v----------------------------
| Role: RoleConsulServerCerts | | Role: RoleHostManagerServerCerts |
------------------------------- ------------------------------------
| issues
|-----------------------------------
| |
---v----------------- ---v------------------
| consul server | | host manager |
| server.crt/key.pem| | server.crt/key.pem |
--------------------- ----------------------
```
Questions:
1. What happens when the authz server goes down?
1. How does revocation propagate?
1. What type of authorization header does a resource server receive?
1. How does a service explain why a subject is not able to access a resource?
1. Does this impact authn for each service?
1. Do we delegate entitlement checks to the authz server to perform billing checks?
1. Is there concern that every Authz check assumes a Most Privileged Access
check and there is no way to reduce privileges for specific sessions?
1. How does impersonation work?
1. How does delegated authorization work? e.g. temporary developer or support access?
Authenticatable:
* User
* Team
* AgentJob
* AgentPool
* TaskResult
* Run
TODO:
* Example of Token Introspection Endpoint.
* Example of Grant Exchange.
* Example of Token Revocation.
* Example of JWT Token with Claims/permissions.
* Example of elevated vs reduced permissions. (sudo mode vs low priv mode)
### References:
* [HCP-007 Resource hierarchy and IAM](https://docs.google.com/document/d/1sawA84ZLt768RIi4VZuCfVUSthAcpcc4ufAkWj-9nlc)
* [HCP-104 Permission naming](https://docs.google.com/document/d/1ZKBRVBKqZU_l4WcKLugYgY_IUACM4SGHWpnJAuWUf70)
* [HCP-128 Internal Operators](https://docs.google.com/document/d/1x2z0jSOGt0l-sHsbBunepOJeuR62yL31_otNmkd0KNc)
* [HCP-167 Human operators RBAC](https://docs.google.com/document/d/14wluO-VnTz5ku5qN5KDkBZCoBgtOZLobMK4Fb1yfn6w)
* [HCP-183 Provisioning roles and permissions](https://docs.google.com/document/u/0/d/10gl7CaoISY5dIqEeIoCdES2yQrrJn26bIUp0mHhvBDk)
* [Presentation: Alex Dadgar](https://hashicorp.zoom.us/rec/share/_mMXheCQJuXTdblyq3uzNsq8PNYj3tI-r2pVJNU-QWSzx3TrvghRJ2AJex-4WHZQ.CRT--WKINJRLg1-b) password: `*y$cLK39`
* [Presentation: Joe](https://hashicorp.zoom.us/rec/share/v8FpIZfpxmhOZ5HJ6WjQW4whBYP3X6a813BNrPALy034-oF5wTfbterEkePMGqM) password: `&445zfl0`
* [RFC 6749 - OAuth 2.0 Authz Framework](https://datatracker.ietf.org/doc/html/rfc6749)
* [RFC 7519 - JSON Web Token (JWT)](https://datatracker.ietf.org/doc/html/rfc7519)
* https://github.com/hashicorp/cloud-resource-manager
|