diff options
| author | mo khan <mo@mokhan.ca> | 2022-04-13 09:44:31 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2022-04-13 09:44:31 -0600 |
| commit | f50684ff437d7880272b34de189c3d0421b0b44d (patch) | |
| tree | 3766c825ec4a2c31736d73bab3e23bb704cb911a | |
| parent | c20c22779c0f6e8db2d028a5ad1ee6dbba08008b (diff) | |
update notes on oidc flow
| -rw-r--r-- | doc/run-identity/README.md | 209 | ||||
| -rwxr-xr-x | src/oidc/bin/01_authz_code | 2 | ||||
| -rwxr-xr-x | src/oidc/bin/02_authz_code_token_request | 19 |
3 files changed, 190 insertions, 40 deletions
diff --git a/doc/run-identity/README.md b/doc/run-identity/README.md index 8587512..a83929d 100644 --- a/doc/run-identity/README.md +++ b/doc/run-identity/README.md @@ -23,10 +23,9 @@ Related Field Requests: To Learn: -* [ ] the OIDC flows. -* [ ] the Vault API. -* [ ] the key material available to a Terraform run context. - +* [X] the OIDC flows. +* [X] the Vault API. +* [X] the key material available to a Terraform run context. 1. In cloud provider, create OIDC trust between cloud role and TFC Workspace. 1. In run task, generate a token via OIDC Provider before apply step. @@ -34,40 +33,174 @@ To Learn: ```plaintext -Is it like this? - ------- ---------------- ---------- - | TFC | | OIDC Provider| | runner | - ------- ---------------- ---------- - | | | - |--- request token ----->| | - | | | - |<----- return token ----| | - | | - | | - | | - |---- inject secrets ---------------------->| - -or like this ... - - ------- ---------- --------- - | TFC | | Runner | | Vault | - ------- ---------- --------- - * aws access/secret - --------> - * job description - * a way to get key material from Vault. (token) - * config version data. - --------> give me the secrets - * do the thing - <------- return the job status - -1. schedule run of apply. -2. key material to do the apply. - * aws access/secret key - * environment vars -3. low ttl key material to do the things. + |<--- 1. fetch .well-known/openid-configuration + | | + |---- 2. return public keys ------->| + | | + ------- ---------------- ---------- --------------------- + | TFC | | OIDC Provider| | runner | | AWS/Azure/GCP/Vault | + ------- ---------------- ---------- --------------------- + | | | | + |- 3. request id token ->| | | + | | | | + |<-4. return id token ---| | | + | | | + |>--5. provide id token ------------------------------------>| + | | + |<---6. return secrets ------------------------------------<| + | | | + |---7. inject secrets ------------------->| | + | | + |-- 8. do things ->| ``` +1. the identity provider is registered with AWS/Azure/GCP/Vault. + * the `/.well-known/openid-configuration` endpoint is used to fetch metadata. +2. the openid metadata is returned. + * this metadata is used to validate the integrity of JWT's that it receives in step 5. + ```bash + モ curl https://dev-klipadbq.us.auth0.com/.well-known/openid-configuration | jq + { + "issuer": "https://dev-klipadbq.us.auth0.com/", + "authorization_endpoint": "https://dev-klipadbq.us.auth0.com/authorize", + "token_endpoint": "https://dev-klipadbq.us.auth0.com/oauth/token", + "device_authorization_endpoint": "https://dev-klipadbq.us.auth0.com/oauth/device/code", + "userinfo_endpoint": "https://dev-klipadbq.us.auth0.com/userinfo", + "mfa_challenge_endpoint": "https://dev-klipadbq.us.auth0.com/mfa/challenge", + "jwks_uri": "https://dev-klipadbq.us.auth0.com/.well-known/jwks.json", + "registration_endpoint": "https://dev-klipadbq.us.auth0.com/oidc/register", + "revocation_endpoint": "https://dev-klipadbq.us.auth0.com/oauth/revoke", + "scopes_supported": [ + "openid", + "profile", + "offline_access", + "name", + "given_name", + "family_name", + "nickname", + "email", + "email_verified", + "picture", + "created_at", + "identities", + "phone", + "address" + ], + "response_types_supported": [ + "code", + "token", + "id_token", + "code token", + "code id_token", + "token id_token", + "code token id_token" + ], + "code_challenge_methods_supported": [ + "S256", + "plain" + ], + "response_modes_supported": [ + "query", + "fragment", + "form_post" + ], + "subject_types_supported": [ + "public" + ], + "id_token_signing_alg_values_supported": [ + "HS256", + "RS256" + ], + "token_endpoint_auth_methods_supported": [ + "client_secret_basic", + "client_secret_post" + ], + "claims_supported": [ + "aud", + "auth_time", + "created_at", + "email", + "email_verified", + "exp", + "family_name", + "given_name", + "iat", + "identities", + "iss", + "name", + "nickname", + "phone_number", + "picture", + "sub" + ], + "request_uri_parameter_supported": false + } + ``` +3. TFC starts a plan, apply etc. by requesting (generating?) an `id_token` + * `id_token` can be obtained via an authz code flow, implicit flow or hybrid flow. + ```bash + curl -s \ + -u "client_id:client_secret" \ + --basic \ + -d "grant_type=authorization_code&code=example&redirect_uri=http://localhost:3000/oauth/callback" \ + "https://dev-klipadbq.us.auth0.com/oauth/token" + ``` +4. the `id_token` that is returned is a signed JWT + * signature is a hash of content encrypted with private key. + * signature can be decrypted by public key found in metadata exchange. + * hash is recomputed by aws to ensure that the data hasn't been tampered with. + ```json + { + "access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYta2xpcGFkYnEudXMuYXV0aDAuY29tLyJ9..kpYUjY8jDc2kRVat.noMdBQplkqhibQhYsz5pWr84Y9KkYl5XsS4IPQhq0EOa0nsy7tqAyH0viGKsFNZ2qxnckE2qk7YqDPGsbgSR_pQlsxGODllWEjVxhRRSDehHkWf9h5rBsMS0bVPbHRbRp_z9hSmzXdtd3xRWHgMN35tu3cylRqnWLgp4bVZF8UA4sEPHe6wZFWrkPq_YCYhTDGoFsxk-6WXy4_r6xKIttWeXKEA0bTADsERKBTfRNI5F7F4-iTHd9VQl4HItoRfDz48cp86LD1AiuES-mMtPgP9HaWbqo9O4UDk9NXs_awhKfyNy.uNjG1xpLDnc4Km9oHcFwNg", + "id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA", + "scope":"openid", + "expires_in":86400, + "token_type":"Bearer" + } + ``` + ```irb + irb(main):001:0> require 'base64' + irb(main):002:0> x = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA' + => "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M... + irb(main):003:0> x.split('.') + => + ["eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9", + "eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30", + "R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA"] + irb(main):004:0> Base64.decode64(x.split('.')[0]) + => "{\"alg\":\"RS256\",\"typ\":\"JWT\",\"kid\":\"Q6Oev_6S2HCkuJTWP79kt\"}" + irb(main):005:0> Base64.decode64(x.split('.')[1]) + => "{\"iss\":\"https://dev-klipadbq.us.auth0.com/\",\"sub\":\"auth0|62563888f7f0f500683f7a9e\",\"aud\":\"ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO\",\"iat\":1649823153,\"exp\":1649859153}" + ``` +5. TFC sends the `id_token` to the token service for the cloud provider. e.g. [STS][1] + ```bash + モ aws sts assume-role-with-web-identity \ + --role-arn "arn:aws:iam::119201842733:role/idp-web-identity-role" \ + --role-session-name="example-1" \ + --duration-seconds 3600 \ + --web-identity-token="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA" --output json | cat + ``` +6. Cloud provider returns secrets. + ```json + { + "Credentials": { + "AccessKeyId": "ASIARXQH3YYWQMPAN57M", + "SecretAccessKey": "nRDvl9q6xoDtvLhha16mOQse9r03XoL2Yw6yMtwp", + "SessionToken": "FwoGZXIvYXdzEL7//////////wEaDCdzgBb1TNJKqqghGSLXAim8vKlHEDn/MxcIsIWnPloA+muPpcvh27zTlKg0XOAVHP6gHudFZHtHJY3L6Lnisf6np/7rstaHqGQy6Fa9tr47KHZtkhQRaDcrpKMgGc9v3VqP4g72k3NNg2zgzWThJEfvNge/RyabpIY1oqju9rK9CS3I7y8ntW4e/8KTxeYIniWgAPBrFJlnDm+vahTtsg/04OkuL+iIpfI+FaUBzTdzZGaE3cKztJX1e/0NpmOGLx5HCkaF0tn9MeZBeSJ/Z/pF4fAZK12+uN0pLvZOkMta+lFhMWlbzqF6pPiruF6PUv6iGILyE85JA/uM6ZerV3RiF4YdxyO5NOnq4USRzdxLQq9IqD5aZNeT1ZnbDPZR4yhztni01t6MB5DtXpaweRdFGEK/cT0aquOGYjYs6qVjuZOnqrUdObBk/V9R9TYuhur2StzyWeXozWSehfr/j/qovO39y1Mo9J3ZkgYyJArNFYwaGf/X2emoBDq/Jl5V2hEiFxANPW7LAhquWzIwIjDQBA==", + "Expiration": "2022-04-13T05:17:56+00:00" + }, + "SubjectFromWebIdentityToken": "auth0|62563888f7f0f500683f7a9e", + "AssumedRoleUser": { + "AssumedRoleId": "AROARXQH3YYWSI3UUY4XD:example-1", + "Arn": "arn:aws:sts::119201842733:assumed-role/idp-web-identity-role/example-1" + }, + "Provider": "arn:aws:iam::119201842733:oidc-provider/dev-klipadbq.us.auth0.com/", + "Audience": "ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO" + } + ``` +7. TFC injects secrets into the `Run`. I don't know how. Config variables, maybe? +8. The `Run` makes API calls to the cloud provider using the `AWS_ACCESS_KEY_ID` and`AWS_SECRET_KEY` env vars that were injected. + # Vault Start the server: @@ -151,5 +284,7 @@ Acceptance Criteria: To think about: 1. NTP syncronization to ensure time matches from client to server. +1. X.509 certificate expiration management? 1. Who is on the app-sec team? (Brian?) -1. x.509 certificate expiration. + +[1]: https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html diff --git a/src/oidc/bin/01_authz_code b/src/oidc/bin/01_authz_code index fa96133..427bd5f 100755 --- a/src/oidc/bin/01_authz_code +++ b/src/oidc/bin/01_authz_code @@ -4,3 +4,5 @@ set -e cd "$(dirname "$0")/.." curl -v -s "http://localhost:8282/authorize?response_type=code&scope=openid&client_id=f00d&state=potatoe&redirect_uri=https://client.example.org/callback" + +curl -v -s "https://dev-klipadbq.us.auth0.com/authorize?response_type=code&scope=openid&client_id=ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO&state=potatoe&redirect_uri=http://localhost:3000/oauth/callback" diff --git a/src/oidc/bin/02_authz_code_token_request b/src/oidc/bin/02_authz_code_token_request index 9e1f221..710a8c2 100755 --- a/src/oidc/bin/02_authz_code_token_request +++ b/src/oidc/bin/02_authz_code_token_request @@ -5,7 +5,20 @@ cd "$(dirname "$0")/.." curl -s \ -vv \ - -u "client_id:client_secret" \ + -u "ymhh1trZ8TcqUPj3XeZoz27KjXPhAmhO:FZv9M-ANpFMHN8hNvURSuAcuMkriQX9-Ltz49SqVFxCgclcBNrms-BOFjUrVwO6U" \ --basic \ - -d "grant_type=authorization_code&code=example&redirect_uri=https://client.example.org/callback" \ - "http://localhost:8282/token" | jq '.' + -d "grant_type=authorization_code&code=kO_gvoj1pTF3z34T7jxVzahdfuEpmJFiuv29KetV09Zcv&redirect_uri=http://localhost:3000/oauth/callback" \ + "https://dev-klipadbq.us.auth0.com/oauth/token" + + +# { +# "access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYta2xpcGFkYnEudXMuYXV0aDAuY29tLyJ9..kpYUjY8jDc2kRVat.noMdBQplkqhibQhYsz5pWr84Y9KkYl5XsS4IPQhq0EOa0nsy7tqAyH0viGKsFNZ2qxnckE2qk7YqDPGsbgSR_pQlsxGODllWEjVxhRRSDehHkWf9h5rBsMS0bVPbHRbRp_z9hSmzXdtd3xRWHgMN35tu3cylRqnWLgp4bVZF8UA4sEPHe6wZFWrkPq_YCYhTDGoFsxk-6WXy4_r6xKIttWeXKEA0bTADsERKBTfRNI5F7F4-iTHd9VQl4HItoRfDz48cp86LD1AiuES-mMtPgP9HaWbqo9O4UDk9NXs_awhKfyNy.uNjG1xpLDnc4Km9oHcFwNg", +# "id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoic2NaN2xRVkZReHliVjJrbzhqU2RYUm9rZ1hzSktFOUsiLCJpYXQiOjE2NDk4MjEyNjUsImV4cCI6MTY0OTg1NzI2NX0.kLGLXR_5qCXBKJCkh87iiXXqz3qVKW_q-19sGVZ5cRM9k6zIPZrtr-CerYAkc75uKxXYCbSrGVAnFUjSYRofz8f3m1n1jwScXnU3gJ0ZZza3p167_KfHfa6VZYtTjVSivCIP3gWfuddNPLNl5CQNN5UKzzmed1Qb5Vly3kHdwK-6DZIDArW39jJT65QnyHuTBMCt6l6yNgJ2Xg5b2tawFFzqwa1MbR-MHWtOP2dbhSEv_mPnqw_GyDeXa9UtEhshTAUCAxGuzSH-YKZOf0e2FjTZA_EhPNp0zywq7y627Ucjzy6P8HGg9y0-y0vb4se9LrxJMeuKjWRukgM-51BtRA", +# "scope":"openid", +# "expires_in":86400, +# "token_type":"Bearer" +# } + + +# {"access_token":"eyJhbGciOiJkaXIiLCJlbmMiOiJBMjU2R0NNIiwiaXNzIjoiaHR0cHM6Ly9kZXYta2xpcGFkYnEudXMuYXV0aDAuY29tLyJ9..BtPj7UDZWyCL29Nt.0pBVp02RgDRxdw1qYif-zPWvgH-UWrxLCuZU8cM2fn-GEufPyZO379Fj33aiMQT72nhUUjYGGw6yDtSlQt6xxJj6C2NE7ELKQAAN97QeFnWgcyyc4uM6Bv7c0060iYX_poLbNS3qwtG63GShzT7aD6u8arG3sWjOo8UTNp4RhJ7FDVpifs5pTfEeDb90aHUb_1_8sokU9q-QrpXYoXfEiw-lIIEEE0AjRmD7kYWviB1Gvnl4iX_QCDsvUSfNflH7th_qsBElnijgzaUeiQWYn4YSCHfOB56D61jttpTIX2s9m2zy.qgmWnYJCUEqpI4ak-C-ctA","id_token":"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlE2T2V2XzZTMkhDa3VKVFdQNzlrdCJ9.eyJpc3MiOiJodHRwczovL2Rldi1rbGlwYWRicS51cy5hdXRoMC5jb20vIiwic3ViIjoiYXV0aDB8NjI1NjM4ODhmN2YwZjUwMDY4M2Y3YTllIiwiYXVkIjoieW1oaDF0clo4VGNxVVBqM1hlWm96MjdLalhQaEFtaE8iLCJpYXQiOjE2NDk4MjMxNTMsImV4cCI6MTY0OTg1OTE1M30.R_zm-f2e6ZVKW73ycPXbBtoBk8gGNytiol4ET4RtNTmgTElFHNDUmyHJDTJbzyHACOju5RcR4o0kpwxdkCmZy7iQw1U4JphAhb1Na4wKHJqk7zn1wJ-hrHou7QGnuVufQTvLnxyxcF6AMc5gxi3CbQf1p5NH0JQpdgc7R-tiQDMV4sa7mWMdVVNHv7oIJFu7PKuPKkg9Aox71dtq-e5_Ucth7JNkDHV61xvJ3L6UoPk9BVDqj4pT84T_ucfKsREdS-_6_2vTneDycxl1UW7_e3UTXpvsaui87LKSBs4L2feOuWTxRL62-XKN--D02tLY6nLdu-OAFEnLy1NX8h0qqA","scope":"openid","expires_in":86400,"token_type":"Bearer"}~/src/github.com/hashicorp/xlgmokha/src/oidc [main] + |
