Slide 1

Slide 1 text

Eric Chiang @erchiang | [email protected] Kubernetes Access Control with dex

Slide 2

Slide 2 text

1. Intro to dex 2. Kubernetes authn 3. Kubernetes authz 4. The future Today’s agenda!

Slide 3

Slide 3 text

● Open-source https://github.com/coreos/dex ● OAuth2 Identity provider ● OpenID Connect enabled ● Federated Dex

Slide 4

Slide 4 text

● Open-source https://github.com/coreos/dex ● OAuth2 Identity provider ● OpenID Connect enabled ● Federated Let the user login however the want. Provide an identity service to other applications. Dex

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

Dex: OAuth2

Slide 7

Slide 7 text

Dex: OAuth2 Application End user Provider

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

Dex: OAuth2 Application End user Provider

Slide 10

Slide 10 text

Dex: OAuth2 Application End user Provider dex

Slide 11

Slide 11 text

Dex: OpenID Connect

Slide 12

Slide 12 text

● Not OpenID, OpenID 1.0, or OpenID 2.0 Dex: OpenID Connect

Slide 13

Slide 13 text

● Not OpenID, OpenID 1.0, or OpenID 2.0 ● Thin layer on top of OAuth2 ● Almost everything is the same Dex: OpenID Connect

Slide 14

Slide 14 text

● Not OpenID, OpenID 1.0, or OpenID 2.0 ● Thin layer on top of OAuth2 ● Almost everything is the same ● Standardizes things left out of OAuth2 ● Easier to get user info ● Discovery mechanisms Dex: OpenID Connect

Slide 15

Slide 15 text

How do I use it? Dex: OpenID Connect

Slide 16

Slide 16 text

config := oauth2.Config{ ClientID: os.Getenv("client_id"), ClientSecret: os.Getenv("client_secret"), Endpoint: oauth2.Endpoint{ AuthURL: "https://a.com/auth", TokenURL: "https://a.com/token", }, RedirectURL: "https://myapp.com/callback", Scopes: []string{"email"}, } OAuth2

Slide 17

Slide 17 text

config := oauth2.Config{ ClientID: os.Getenv("client_id"), ClientSecret: os.Getenv("client_secret"), Endpoint: oauth2.Endpoint{ AuthURL: "https://a.com/auth", TokenURL: "https://a.com/token", }, RedirectURL: "https://myapp.com/callback", Scopes: []string{"email", "openid"}, } OpenID Connect

Slide 18

Slide 18 text

{ "access_token": "SlAV32hkKG", "token_type": "Bearer", "refresh_token": "8xLOxBtZp8", "expires_in": 3600 } OAuth2: Token Response

Slide 19

Slide 19 text

{ "access_token": "SlAV32hkKG", "token_type": "Bearer", "refresh_token": "8xLOxBtZp8", "expires_in": 3600, "id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjFlOWdkazcifQ.ewogImlzc yI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5 NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZ fV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5Nz AKfQ.ggW8hZ1EuVLuxNuuIJKX_V8a_OMXzR0EHR9R6jgdqrOOF4daGU96Sr_P6q Jp6IcmD3HP99Obi1PRs-cwh3LO-p146waJ8IhehcwL7F09JdijmBqkvPeB2T9CJ NqeGpe-gccMg4vfKjkM8FcGvnzZUN4_KSP0aAp1tOJ1zZwgjxqGByKHiOtX7Tpd QyHE5lcMiKPXfEIQILVq0pc_E2DzL7emopWoaoZTF_m0_N0YzFC6g6EJbOEoRoS K5hoDalrcvRYLSrQAZZKflyuVCyixEoV9GfNQC3_osjzw2PAithfubEEBLuVVk4 XUVrWOLrLl0nx7RkKU8NXNHq-rvKMzqg" } OpenID Connect: Token Response

Slide 20

Slide 20 text

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwi YWRtaW4iOnRydWV9.EkN- DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8j O19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuh tF39yxJPAjUESwxk2J5k_4zM3O- vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE JSON Web Token

Slide 21

Slide 21 text

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwi YWRtaW4iOnRydWV9.EkN- DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8j O19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuh tF39yxJPAjUESwxk2J5k_4zM3O- vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE { "alg": "RS256", "typ": "JWT" } JSON Web Token

Slide 22

Slide 22 text

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwi YWRtaW4iOnRydWV9.EkN- DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8j O19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuh tF39yxJPAjUESwxk2J5k_4zM3O- vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE { "sub": "1234567890", "name": "John Doe", "admin": true } JSON Web Token

Slide 23

Slide 23 text

eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwi YWRtaW4iOnRydWV9.EkN- DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8j O19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuh tF39yxJPAjUESwxk2J5k_4zM3O- vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE C~ �'��cD���w�����v���s^ [7d���(��8" ��L�#;_V� ��Ɋ3K��f��c�}k��9�t���k�E:�g+��]��O5K d؞d����ﯵ�F�*8!��),�'ٓ�& =����Ȋ� JSON Web Token

Slide 24

Slide 24 text

Real id_token I requested from Google: eyJhbGciOiJSUzI1NiIsImtpZCI6IjQ5YWY5N2RmMmQ5MzY0MDJjN2Y1MzM4ZjM2MGQxMWFhYzJlZT JjM2QifQ. eyJpc3MiOiJodHRwczovL2FjY291bnRzLmdvb2dsZS5jb20iLCJhdF9oYXNoIjoiazRicDVjN1dHSU ZTSHp0QUJUcFloZyIsImF1ZCI6IjgxMjg3NTY3MTU0My1wZWpocGJwMjNiN3FtN241MmplMXY5amJn ZDFvN2VoOC5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsInN1YiI6IjEwNTE4MTcxOTk4MTY0MD E1NjU2NyIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJhenAiOiI4MTI4NzU2NzE1NDMtcGVqaHBicDIz YjdxbTduNTJqZTF2OWpiZ2QxbzdlaDguYXBwcy5nb29nbGV1c2VyY29udGVudC5jb20iLCJoZCI6Im NvcmVvcy5jb20iLCJlbWFpbCI6ImVyaWMuY2hpYW5nQGNvcmVvcy5jb20iLCJpYXQiOjE0NjAwNjk1 MDAsImV4cCI6MTQ2MDA3MzEwMCwibmFtZSI6IkVyaWMgQ2hpYW5nIiwiZ2l2ZW5fbmFtZSI6IkVyaW MiLCJmYW1pbHlfbmFtZSI6IkNoaWFuZyIsImxvY2FsZSI6ImVuIn0. oGKiYmScs9iaj7AnDJgBY30VyJK- NSSSfSnwdfohCcEsO6ixCfdWOXQ7ulmbUkHu45PXrgahthbIgFpFw60W7nALT8k75ubV2VheJeRvlR icZ8ct_eaAC4wLvRAxdJZBlyiFjzqBeTdapP8jCgztHPbDOXMtdMfYxIFp1pnykbFawH_wnPpKDU8n 8MmHw109j8hTcx1MArRVS8Ikq0hHHvpe462NgEvC9vn813NdqqUsERJgHyTMee5qReGaZsJQ- UtxJqfi2UGpYEog1uL5HCIDlAyGNkY2tnP0eaFmaKOnkVZWZu98OAxbEEDLPy-Rr- CofpvEjKjYtpNhuFMTQA JSON Web Token: ID Token

Slide 25

Slide 25 text

{ "iss": "https://accounts.google.com", "at_hash": "k4bp5c7WGIFSHztABTpYhg", "aud": "812875671543-pejhpbp23b7qm7n52je1v9jbgd1o7eh8.apps. googleusercontent.com", "sub": "105181719981640156567", "email_verified": true, "azp": "812875671543-pejhpbp23b7qm7n52je1v9jbgd1o7eh8.apps. googleusercontent.com", "hd": "coreos.com", "email": "[email protected]", "iat": 1460069500, "exp": 1460073100, "name": "Eric Chiang", "given_name": "Eric", "family_name": "Chiang", "locale": "en" } JSON Web Token: ID Token

Slide 26

Slide 26 text

How do I verify the signature? JSON Web Token: ID Token

Slide 27

Slide 27 text

https://dex.example.com/.well-known/openid-configuration OpenID Connect: Discovery

Slide 28

Slide 28 text

https://dex.example.com/.well-known/openid-configuration ● Automatically discover information about the provider ● Token, auth endpoint ● Public keys OpenID Connect: Discovery

Slide 29

Slide 29 text

Kubernetes Authn/Authz

Slide 30

Slide 30 text

● Authentication ○ Figuring out who you are ○ Example: A driver's license ● Authorization ○ Rules for who can do what ○ Example: You must be 21 to drink Kubernetes Authn/Authz

Slide 31

Slide 31 text

● TLS ● Password ● Token Kubernetes Authn Plugins

Slide 32

Slide 32 text

TLS certificates Kubernetes Authn Plugins: TLS

Slide 33

Slide 33 text

● Password files ● Keystone (openstack) Kubernetes Authn Plugins: Password

Slide 34

Slide 34 text

● Token files ● OpenID Connect Kubernetes Authn Plugins: Token

Slide 35

Slide 35 text

● Token files ● OpenID Connect ○ Look at ID Token to determine who you are Kubernetes Authn Plugins: Token

Slide 36

Slide 36 text

./kube-apiserver \ --oidc-issuer-url=https://dex.example.com \ --oidc-client-id=example-app \ --oidc-username-claim=email \ # ... kubectl config set-credentials --token=$ID_TOKEN Kubernetes Authn Plugins: OIDC

Slide 37

Slide 37 text

Quick aside: Kubernetes “plugins”

Slide 38

Slide 38 text

Dex Federation and Kubernetes

Slide 39

Slide 39 text

Dex federation and Kubernetes

Slide 40

Slide 40 text

Dex Federation and Kubernetes dex

Slide 41

Slide 41 text

Dex Federation and Kubernetes dex

Slide 42

Slide 42 text

Kubernetes Authz

Slide 43

Slide 43 text

● AllowAll ● DenyAll ● ABAC File Kubernetes Authz

Slide 44

Slide 44 text

abac.jsonl (pretty printed) { "user": "eric", "namespace": "tectonic-prod", "resource": "service" "readonly": true, } { "group": "tectonic", "namespace": "tectonic-dev", "resource": "*" } Kubernetes Authz: ABAC File

Slide 45

Slide 45 text

● AllowAll ● DenyAll ● ABAC File Kubernetes Authz

Slide 46

Slide 46 text

● AllowAll ● DenyAll ● ABAC File ● Webhook Kubernetes Authz

Slide 47

Slide 47 text

./kube-apiserver \ --authorization-mode=Webhook \ --authorization-webhook-config-file=webhookconfig \ # ... Kubernetes Authz Plugins: Webhook

Slide 48

Slide 48 text

./kube-apiserver \ --authorization-mode=Webhook \ --authorization-webhook-config-file=webhookconfig \ # ... clusters: - name: my-authz-service cluster: server: https://authz.example.com/webhook Kubernetes Authz Plugins: Webhook

Slide 49

Slide 49 text

POST /webhook HTTP/1.1 Host: authz.example.com { "apiVersion": "authorization.k8s.io/v1beta1", "kind": "SubjectAccessReview", "spec": { "resourceAttributes": { "namespace": "kittensandponies", "verb": "GET", "group": "v1", "resource": "pods" }, "user": "jane" } } Kubernetes Authz Plugins: Webhook

Slide 50

Slide 50 text

if review.user == "jane" && review.Namespace != "development" { return errors.New("unauthorized") } Kubernetes Authz Plugins: Webhook

Slide 51

Slide 51 text

The Future

Slide 52

Slide 52 text

The Future ● Authn ○ Continue to improve the login (kubectl login) ○ Automatic refreshing of tokens in kubeconfig ○ Grouping users in dex

Slide 53

Slide 53 text

The Future ● Authn ○ Continue to improve the login (kubectl login) ○ Automatic refreshing of tokens in kubeconfig ○ Grouping users in dex ● Authz ○ Better upstream authz solution ○ Policies and roles

Slide 54

Slide 54 text

The Future: Authz ● Webhooks are good for integrating with existing solutions ● Kubernetes should ship with a more capable default ● Upstream RBAC inspired by Openshift

Slide 55

Slide 55 text

Thank you! Eric Chiang @erchiang | [email protected] We’re hiring in all departments! Email: [email protected] Positions: coreos.com/careers

Slide 56

Slide 56 text

coreos.com/fest - @coreosfest May 9 & 10, 2016 - Berlin, Germany