diff options
Diffstat (limited to 'doc/run-identity/README.md')
| -rw-r--r-- | doc/run-identity/README.md | 209 |
1 files changed, 172 insertions, 37 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 |
