profile
viewpoint
Daniele Polencic danielepolencic @learnk8s London ✈Singapore Teaching containers and Kubernetes at @learnk8s ⎈ Certified Kubernetes Administrator

behavior3/behavior3js 291

Behavior3 client library for Javascript (Behavior Trees for Javascript)

chrisns/kubectl-passman 32

kubectl plugin that provides the missing link/glue between common password managers and kubectl

danielepolencic/awesome-kubernetes 4

A curated list for awesome kubernetes sources :ship::tada:

danielepolencic/channel4 2

Super simple CSP channels for Javascript (like Clojurescript's core.async, or Go channels)

danielepolencic/awesome-microservices 1

A curated list of Microservice Architecture related principles and technologies.

danielepolencic/CKAD-exercises 1

A set of exercises to prepare for Certified Kubernetes Application Developer exam by Cloud Native Computing Foundation

chrisns/k8sdraw 0

Graphical drawings of kubernetes infrastructure.

danielepolencic/aranna 0

Entity Component System

starteddanielepolencic/awesome-kubernetes

started time in 2 days

startedJedWatson/react-select

started time in 3 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha 52ba4d2a08e1c63b8e7e15faa8d1745c3433c620

Update logs to be prettier

view details

push time in 6 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha aba3516f98398192bd4f41cbab84216f168c4ba0

fix

view details

push time in 6 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha bcadcebe2c66f0915f89fbe8fdd15c3c6681ae0f

TokenReview code rearrange

view details

push time in 6 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha 26858fab0dd3ea26b69bac61aa4a1555ea4cb143

Add link to 1.20 GA

view details

push time in 7 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha c9f66dcfe4a609195a2bb481238d7dc732994535

Add a command for running an autoformat of the content

view details

Amit Saha

commit sha ff9ae06b2e65a6c48b5e1d289ecc590ea48a0957

init

view details

Amit Saha

commit sha 81e366e6f66c8b5b928d14cbb07960fbf32098c3

Update micros-authentication.tsx

view details

Amit Saha

commit sha c63dba6f7ce0e033cf0adbc3d9987c97e6c1bc45

Update content.md

view details

Amit Saha

commit sha 613eca86ffe2f0161ef993f6d55f6b615ff2dbcb

Add files via upload

view details

Amit Saha

commit sha da8268d44ea8edc99d29619f8b78b74c833526e4

Update content.md

view details

Amit Saha

commit sha 9d46295258c3054f505be1f0eb7d1519d1dbf4e5

Delete yaml-validate.png

view details

Amit Saha

commit sha 39062317c792639e399b39ca93bafb8633d27f6c

Delete yaml-validate.svg

view details

Amit Saha

commit sha 949b1469bef448f06a1707759295ed7ad437badb

Update content.md

view details

Amit Saha

commit sha 6dcd5ab961606a7156f950879c0b0454b0915715

Update content.md

view details

Amit Saha

commit sha 37802a361283e1cd949e902cd61ee3e5a62f39b9

Update content.md

view details

Amit Saha

commit sha b62f85a38b143c741716261f34a799ec98ebfc16

Update content.md

view details

Amit Saha

commit sha 00682c71f843c7c023fe75ff8e729f1410578c51

Update content.md

view details

Amit Saha

commit sha ee06315a072e6a40b815d15a57bacc209dbc5819

Update content.md

view details

Amit Saha

commit sha 15aef2e64056979580991eecc9e4710b63f8acaf

Update content.md

view details

Amit Saha

commit sha abf4b4c0da99271fce165faf3a4c1b1bab19705f

Update register.ts

view details

Amit Saha

commit sha f92f5db53c19d41ce2b949a2fe8a055f1ec6e5a9

fix

view details

Amit Saha

commit sha d16f9ca01e58a648e1ac669c7fad7514c91afeff

update

view details

Amit Saha

commit sha 2c8aea83bd06f350b84e8cc78d336ef22a4bd84e

update

view details

Amit Saha

commit sha e8eab12e9546ee6f645903e5dcb1a172682da64d

update

view details

push time in 7 days

create barnchlearnk8s/learnk8s.io

branch : dependabot/npm_and_yarn/dot-prop-4.2.1

created branch time in 8 days

PR opened learnk8s/learnk8s.io

Bump dot-prop from 4.2.0 to 4.2.1

Bumps dot-prop from 4.2.0 to 4.2.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/sindresorhus/dot-prop/releases">dot-prop's releases</a>.</em></p> <blockquote> <h2>v4.2.1</h2> <ul> <li>Backport <a href="https://github.com/sindresorhus/dot-prop/commit/3039c8c07f6fdaa8b595ec869ae0895686a7a0f2">https://github.com/sindresorhus/dot-prop/commit/3039c8c07f6fdaa8b595ec869ae0895686a7a0f2</a> to the v4.x release line.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/sindresorhus/dot-prop/commit/c914124f418f55edea27928e89c94d931babe587"><code>c914124</code></a> feat: patch 4.2.0 with fixes for CVE-2020-8116</li> <li>See full diff in <a href="https://github.com/sindresorhus/dot-prop/compare/v4.2.0...v4.2.1">compare view</a></li> </ul> </details> <br />

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


<details> <summary>Dependabot commands and options</summary> <br />

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot merge will merge this PR after your CI passes on it
  • @dependabot squash and merge will squash and merge this PR after your CI passes on it
  • @dependabot cancel merge will cancel a previously requested merge and block automerging
  • @dependabot reopen will reopen this PR if it is closed
  • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
  • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
  • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
  • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

You can disable automated security fix PRs for this repo from the Security Alerts page.

</details>

+3 -3

0 comment

1 changed file

pr created time in 8 days

pull request commentlearnk8s/learnk8s.io

Add a command for running an autoformat of the content

@danielepolencic what do you think?

amitsaha

comment created time in 8 days

pull request commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

@danielepolencic i made a few updates related to authn/authz what do you think?

amitsaha

comment created time in 8 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha f8f012c27d4e2693887a976ac97743c64011fb28

Authentication/Authorization

view details

push time in 8 days

pull request commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

I think the TokenReview API is authentication, but when you use to verify the audience you are implementing custom authorization.

Completely agree with this. So should we just use authentication throughout?

amitsaha

comment created time in 8 days

Pull request review commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

 To issue a request to the Token Review API, you need to create a TokenReview res ```yaml|title=token.yaml kind: TokenReview apiVersion: authentication.k8s.io/v1+metadata:+  name: test spec:-  token: <the token that you want to validate>+  token: <replace with the token to validate> ```  AMIT: this should be refactored. We can use Kubectl + impersonation.  > I am not sure how we can make an API call using impersonation. Quick google didn't return anything-> Also I would prefer this example to be as it is as it shows how this would work in an application running in a +> Also I would prefer this example to be as it is as it shows how this would work in an application running in a > pod and flows nicely into the service implementation in Go. +AMIT: This is where we shine :)+It's a POST request... so it should be `kubectl apply`.++```terminal|command=1|title=bash+kubectl apply -v=8 -f token.yaml+tokenreview.authentication.k8s.io/test created+kubectl get tokenreview+Error from server (MethodNotAllowed): the server does not allow this method on the requested resource+kubectl get tokenreview.authentication.k8s.io+Error from server (MethodNotAllowed): the server does not allow this method on the requested resource+kubectl describe tokenreview.authentication.k8s.io+Error from server (MethodNotAllowed): the server does not allow this method on the requested resource+```++I was ready to give up when I tried adding `-v8` to the apply request.++The response contains the JSON payload.++Next, `kubectl apply -h` reveals that there's a `-o` flag for the output.++And... voila! Validate a token with only kubectl:++```terminal|command=1|title=bash+kubectl apply -o yaml -f token.yaml+```++You're issueing a request using your own account (cluster admin) and validating the token for a Service account.++It's easier to explain, and we skip the part where we connect to the API. The same part is skipped in the Go client too (it's part of the SDK).

How about we use kubectl to show the token review operation but use the token for the service token instead via the --token argument?

Get the token from the secret object

kubectl apply -f t.yaml --token <token from above>

amitsaha

comment created time in 8 days

Pull request review commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

 To issue a request to the Token Review API, you need to create a TokenReview res ```yaml|title=token.yaml kind: TokenReview apiVersion: authentication.k8s.io/v1+metadata:+  name: test spec:-  token: <the token that you want to validate>+  token: <replace with the token to validate> ```  AMIT: this should be refactored. We can use Kubectl + impersonation.  > I am not sure how we can make an API call using impersonation. Quick google didn't return anything-> Also I would prefer this example to be as it is as it shows how this would work in an application running in a +> Also I would prefer this example to be as it is as it shows how this would work in an application running in a > pod and flows nicely into the service implementation in Go. +AMIT: This is where we shine :)+It's a POST request... so it should be `kubectl apply`.++```terminal|command=1|title=bash+kubectl apply -v=8 -f token.yaml+tokenreview.authentication.k8s.io/test created+kubectl get tokenreview+Error from server (MethodNotAllowed): the server does not allow this method on the requested resource+kubectl get tokenreview.authentication.k8s.io+Error from server (MethodNotAllowed): the server does not allow this method on the requested resource+kubectl describe tokenreview.authentication.k8s.io+Error from server (MethodNotAllowed): the server does not allow this method on the requested resource+```++I was ready to give up when I tried adding `-v8` to the apply request.++The response contains the JSON payload.++Next, `kubectl apply -h` reveals that there's a `-o` flag for the output.++And... voila! Validate a token with only kubectl:++```terminal|command=1|title=bash+kubectl apply -o yaml -f token.yaml+```++You're issueing a request using your own account (cluster admin) and validating the token for a Service account.++It's easier to explain, and we skip the part where we connect to the API. The same part is skipped in the Go client too (it's part of the SDK).

Nice find! I think i see your point here - not showing you to access the API directly.

How about we use kubectl to show the token review operation but use the token for the service token instead via the --token argument?

In addition can we still keep the curl bit?

amitsaha

comment created time in 8 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha c024ab9c738cb5c8bc27cb342bbe69ed148afc15

formatting

view details

push time in 9 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha 6b61b05c9c5b1a771c56e28c1b71146b503eb975

Update content.md

view details

push time in 9 days

create barnchlearnk8s/learnk8s.io

branch : add_autofmt_script

created branch time in 11 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha f2e21ce91be7053f1339ea3d2e67648318d2b2b4

update

view details

push time in 11 days

Pull request review commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

+If your infrastructure consists of several applications interacting with each other, you might have faced the issue of securing the communication between services to prevent unauthenticated requests.++Imagine having three apps:++1. An API+1. A data store+1. A secret store++You might want the secret store only to reply to requests to the API and reject any request from the data store.++_How would the secret store decide to authenticate or deny the request?_++A popular approach is to request and pass identity tokens to every call within services.++So instead of issuing a request to the secret store directly, you might need to go through an Authorisation service first, retrieve a token and authenticate your request.++That way, when the data store or the presents the token to the secret store, it is rejected.++However, if the API service presents the same token, it is accepted.++![Three apps](image1.png)++You have several options when it comes to authorisation server:++- You could use static tokens that don't expire. In this case, there is no need for running a dedicated authorization server.+- You could use oAuth by setting up an internal oAuth server.+- You could roll out your own authorisation mechanism such as mutual TLS certificates.++All authorisation servers have to do is to:++1. **Authenticate the caller** - The caller should have a valid and verifiable identity.+1. **Generate a token with a limited scope, validity and the desired audience.**+1. **Validate a token** - Service to service communication is allowed only if the token is legit.++Examples of Authorisation servers are tools such as [Keycloak](https://www.keycloak.org/) or [Dex](https://github.com/dexidp/dex).++You might have not noticed, but even Kubernetes offers the same primitives as the authorisation service with Service Account, Roles and RoleBindings.++In Kubernetes, you assign identities using Service Accounts.++Service accounts are linked to roles to that grant access to resources.++Tokens are generated as soon as you create the Service Account and stored in a Secret.++Users and Pods can use the secret as a mechanism to authenticate to the API and make requests.++You only receive successful replies for the resources you are entitled to consume.++If your Role grant you access to create and delete Pods, you won't be able to amend Secrets, or create ConfigMaps — for example.++_Could you use Service Accounts as a mechanism to authenticate requests between apps in the cluster?_++Kubernetes offers the same primitives to authentication requests just like Keycloak and Dex.++_What if the Kubernetes API could be used as an Authorisation server?_++_Could you use Service Accounts as a mechanism to authenticate requests between apps in the cluster?_++Let's try that.++You will now deploy two services:++1. You will refer to these services as the API service (API) and the Secret store.+1. They are written in the Go programming language and they communicate via HTTP.+1. Each service runs in its own namespaces and use dedicated service accounts.+1. The secret store requires that any client identifies itself before making a request.++## Creating the cluster++You will need access to a Kubernetes cluster with the [ServiceAccountVolume projection](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection) feature enabled.++Don't worry if you don't know what a ServiceAccountVolume is — you will learn more about it later on in the article.++The ServiceAccountVolume projection requires the Kubernetes API server to be started with certain specific API flags.++The support for different managed Kubernetes providers may vary.++However, you can enable it in [minikube](https://github.com/kubernetes/minikube) with:++```terminal|command=1-6|title=bash+minikube start \+  --extra-config=apiserver.service-account-signing-key-file=\+    /var/lib/minikube/certs/sa.key \+  --extra-config=apiserver.service-account-issuer=\+    kubernetes/serviceaccount \+  --extra-config=apiserver.service-account-api-audiences=api+```++You should also clone the repository <https://github.com/amitsaha/kubernetes-sa-volume-demo> as it contains the demo source code that will be referred to in the article.++## Deploying the API component++The API service is a headless web application listening on port 8080.++When a client makes any request to it, the API component:++1. Reads the service account token.+1. Makes a HTTP GET request to the secret store service with the token linked to the Service Account.+1. Forwards the response.++You can deploy the app in the cluster with:++```terminal|command=1|title=bash+kubectl apply -f service_accounts/api/deployment.yaml+namespace/api created+serviceaccount/api created+deployment.apps/app created+```++You can temporarily expose the API with:

I have addressed this - apologies i was being lazy here.

amitsaha

comment created time in 11 days

push eventlearnk8s/learnk8s.io

Amit Saha

commit sha 1871dec4c945a17a0f9111196d530f6694dacc50

Update deployment manifest to expose service Address review comment related to exposing the services from the manifest itself.

view details

push time in 11 days

Pull request review commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

+If your infrastructure consists of several applications interacting with each other, you might have faced the issue of securing the communication between services to prevent unauthenticated requests.++Imagine having three apps:++1. An API+1. A data store+1. A secret store++You might want the secret store only to reply to requests to the API and reject any request from the data store.++_How would the secret store decide to authenticate or deny the request?_++A popular approach is to request and pass identity tokens to every call within services.++So instead of issuing a request to the secret store directly, you might need to go through an Authorisation service first, +retrieve a token and authenticate your request.++That way, when the data store presents a token to the secret store, it is rejected.++However, if the API service presents the same token, it is accepted by the secret store.++There is a certain context associated with the token that allows the secret store to accept a token from the API service+and to reject a token from the data store service. ++This context association and verfification could be implemented in multiple ways.++![Three apps](image1.png)++You have several options when it comes to implementing this mechanism of authentication:++- You could use static tokens that don't expire. In this case, there is no need for running a dedicated authorization server.+- You could use oAuth by setting up an internal oAuth server.+- You could roll out your own authorisation mechanism such as mutual TLS certificates.++All authorisation servers have to do is to:++1. **Authenticate the caller** - The caller should have a valid and verifiable identity.+1. **Generate a token with a limited scope, validity and the desired audience.**+1. **Validate a token** - Service to service communication is allowed only if the token is legit for the two services involved.++Examples of Authorisation servers are tools such as [Keycloak](https://www.keycloak.org/) or [Dex](https://github.com/dexidp/dex).++You might have not noticed, but even Kubernetes offers the same primitives as the authorisation service with Service Account, Roles and RoleBindings.++In Kubernetes, you assign identities using Service Accounts.++Service accounts are then linked to roles to that grant access to resources.++Tokens are generated as soon as you create the Service Account and stored in a Secret.++Users and Pods can use the secret as a mechanism to authenticate to the API and make requests.++You only receive successful replies for the resources you are entitled to consume.++If your Role grant you access to create and delete Pods, you won't be able to amend Secrets, or create ConfigMaps — for example.++_Could you use Service Accounts as a mechanism to authenticate requests between apps in the cluster?_++Kubernetes offers the same primitives to authentication requests just like Keycloak and Dex.++_What if the Kubernetes API could be used as an Authorisation server?_++_Could you use Service Accounts as a mechanism to authenticate requests between apps in the cluster?_++Let's try that.++You will now deploy two services:++1. You will refer to these services as the API service (API) and the Secret store.+1. They are written in the Go programming language and they communicate via HTTP.+1. Each service runs in its own namespaces and use dedicated service accounts.+1. The secret store requires that any client identifies itself before making a request.++## Creating the cluster++You will need access to a Kubernetes cluster with the [ServiceAccountVolume projection](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection) feature enabled.++Don't worry if you don't know what a ServiceAccountVolume is — you will learn more about it later on in the article.++The ServiceAccountVolume projection requires the Kubernetes API server to be started with certain specific API flags.++The support for different managed Kubernetes providers may vary.++However, you can enable it in [minikube](https://github.com/kubernetes/minikube) with:++```terminal|command=1-6|title=bash+minikube start \+  --extra-config=apiserver.service-account-signing-key-file=\+    /var/lib/minikube/certs/sa.key \+  --extra-config=apiserver.service-account-issuer=\+    kubernetes/serviceaccount \+  --extra-config=apiserver.service-account-api-audiences=api+```

Not sure, can you please try with the latest minikube version? I just tried now and it works for me:

$ minikube version
minikube version: v1.15.1
commit: 23f40a012abb52eff365ff99a709501a61ac5876

My script:

% cat start_minikube.sh 
#!/bin/bash

minikube start --extra-config=apiserver.service-account-signing-key-file=/var/lib/minikube/certs/sa.key --extra-config=apiserver.service-account-issuer=kubernetes/serviceaccount --extra-config=apiserver.service-account-api-audiences=api
amitsaha

comment created time in 11 days

Pull request review commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

 export function register(store: Store) {   Gatekeeper.Register(store)   GracefulShutdown.Register(store)   RequestsLimits.Register(store)+  MicroServiceAuthentication.Register(store)

Ah, this is the magic that was needed.

amitsaha

comment created time in 11 days

Pull request review commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

+If your infrastructure consists of several applications interacting with each other, you might have faced the issue of securing the communication between services to prevent unauthenticated requests.++Imagine having three apps:++1. An API+1. A data store+1. A secret store++You might want the secret store only to reply to requests to the API and reject any request from the data store.++_How would the secret store decide to authenticate or deny the request?_++A popular approach is to request and pass identity tokens to every call within services.++So instead of issuing a request to the secret store directly, you might need to go through an Authorisation service first, +retrieve a token and authenticate your request.++That way, when the data store presents a token to the secret store, it is rejected.++However, if the API service presents the same token, it is accepted by the secret store.++There is a certain context associated with the token that allows the secret store to accept a token from the API service+and to reject a token from the data store service. ++This context association and verfification could be implemented in multiple ways.++![Three apps](image1.png)++You have several options when it comes to implementing this mechanism of authentication:++- You could use static tokens that don't expire. In this case, there is no need for running a dedicated authorization server.+- You could use oAuth by setting up an internal oAuth server.+- You could roll out your own authorisation mechanism such as mutual TLS certificates.++All authorisation servers have to do is to:++1. **Authenticate the caller** - The caller should have a valid and verifiable identity.+1. **Generate a token with a limited scope, validity and the desired audience.**+1. **Validate a token** - Service to service communication is allowed only if the token is legit for the two services involved.++Examples of Authorisation servers are tools such as [Keycloak](https://www.keycloak.org/) or [Dex](https://github.com/dexidp/dex).++You might have not noticed, but even Kubernetes offers the same primitives as the authorisation service with Service Account, Roles and RoleBindings.++In Kubernetes, you assign identities using Service Accounts.++Service accounts are then linked to roles to that grant access to resources.++Tokens are generated as soon as you create the Service Account and stored in a Secret.++Users and Pods can use the secret as a mechanism to authenticate to the API and make requests.++You only receive successful replies for the resources you are entitled to consume.++If your Role grant you access to create and delete Pods, you won't be able to amend Secrets, or create ConfigMaps — for example.++_Could you use Service Accounts as a mechanism to authenticate requests between apps in the cluster?_++Kubernetes offers the same primitives to authentication requests just like Keycloak and Dex.++_What if the Kubernetes API could be used as an Authorisation server?_++_Could you use Service Accounts as a mechanism to authenticate requests between apps in the cluster?_++Let's try that.++You will now deploy two services:++1. You will refer to these services as the API service (API) and the Secret store.+1. They are written in the Go programming language and they communicate via HTTP.+1. Each service runs in its own namespaces and use dedicated service accounts.+1. The secret store requires that any client identifies itself before making a request.++## Creating the cluster++You will need access to a Kubernetes cluster with the [ServiceAccountVolume projection](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection) feature enabled.++Don't worry if you don't know what a ServiceAccountVolume is — you will learn more about it later on in the article.++The ServiceAccountVolume projection requires the Kubernetes API server to be started with certain specific API flags.++The support for different managed Kubernetes providers may vary.++However, you can enable it in [minikube](https://github.com/kubernetes/minikube) with:++```terminal|command=1-6|title=bash+minikube start \+  --extra-config=apiserver.service-account-signing-key-file=\+    /var/lib/minikube/certs/sa.key \+  --extra-config=apiserver.service-account-issuer=\+    kubernetes/serviceaccount \+  --extra-config=apiserver.service-account-api-audiences=api+```++You should also clone the repository <https://github.com/amitsaha/kubernetes-sa-volume-demo> as it contains the demo source code that will be referred to in the article.++## Deploying the API component++The API service is a headless web application listening on port 8080.++When a client makes any request to it, the API component:++1. Reads the service account token.+1. Makes a HTTP GET request to the secret store service with the token linked to the Service Account.+1. Forwards the response.++You can deploy the app in the cluster with:++```terminal|command=1|title=bash+kubectl apply -f service_accounts/api/deployment.yaml+namespace/api created+serviceaccount/api created+deployment.apps/app created+```++You can temporarily expose the API with:++```terminal|command=1|title=bash+kubectl --namespace api expose deployment/app --type=NodePort+service/app exposed+```++Retrieve the URL of the app with:++```terminal|command=1|title=bash+minikube --namespace api service deployment --url+http://192.168.99.101:31541+```++_Will you get a successful response from the API server?_++You can issue a request with:++```terminal|command=1|title=bash+curl http://192.168.99.101:31541+Get "<http://app.secret-store.svc.cluster.local">: dial tcp: lookup app.secret-store.svc.cluster.local: no such host+```++This is expected since you haven't yet deployed the secret store service.++_Keep the terminal open._++Open a new terminal to carry out the next set of steps.++## Deploying the Secret store++The secret store service is another headless web application listening on port 8081.++When a client makes any request to it, the Secret store:++1. Looks for a token in the request. If there isn't one, it replies with a HTTP 401 error response.+1. Checks the token with the Kubernetes API for its validity. If it's invalid, it replies with a HTTP 403 response.+1. Replies to the original request.++You can create the secret store with:++```terminal|command=1|title=bash+kubectl apply -f service_accounts/secret-store/deployment.yaml+namespace/secret-store created+serviceaccount/secret-store created+clusterrolebinding.rbac.authorization.k8s.io/role-tokenreview-binding created+deployment.apps/app created+service/app created+```++Now, go back to the previous terminal window with the API service and issue the same request again:++```terminal|command=1|title=bash+curl http://192.168.99.101:31541+Hello from secret store. You have been authenticated+```++The secret store service successfully verified the token and replied to your request.++_But how does all of that work? Let's find out._++Keep the two terminal sessions running and switch to a new (third) terminal session.++## Under the hood++**Service accounts are a way to associate your Kubernetes workload with an identity.**++You can then combine a service account with a Role (or ClusterRole) and a RoleBinding (or ClusterRoleBinding)+to define what or who can access what resources in a cluster.++For example, when you want to restrict reading Secrets only to admin users in the cluster, you can do so using a service account.++Service Accounts aren't just for users, though.++You can authenticate humans as well as applications in the cluster.++If you want your applications to list all the available Pods in the cluster, you will need to create a Service Account that is associated with read-only access to the Pod API.++You deployed two apps that have Service Accounts — let's have a look.++```terminal|command=1,5|title=bash+kubectl get serviceaccount --namespace api+NAME      SECRETS   AGE+api       1         4m5s+default   1         4m5s+kubectl get serviceaccount --namespace secret-store+NAME           SECRETS   AGE+default        1         6m4s+secret-store   1         6m4s+```++Those Service Account are the identities associated with the apps, but they don't define what permissions are granted.++For that, you might need to list the Role and the RoleBinding:++```terminal|command=1,3|title=bash+kubectl get role,rolebinding --namespace api+No resources found in api namespace.+kubectl get role,rolebinding --namespace secretstore+No resources found in secretstore namespace.+```++There are none!++_How come you can have a Service Account without a Role and RoleBinding?_++You created an empty Service Account that doesn't have any sort of permission.++However, you can use it to authenticate your request to the Kubernetes API (but you can't create, update, delete, etc. resources).++Service accounts are useful and straightforward, but you should know that:++### 1. When you create a Service Account, Kubernetes creates a companion Secret object with a token++You use the token to authenticate with the Kubernetes API.++In this example, you can inspect the Service Account and find the token with:++```terminal|command=1|title=bash+kubectl --namespace api describe serviceaccount api+Name:                api+Namespace:           api+Mountable secrets:   api-token-ttr8q+Tokens:              api-token-ttr8q+```++Which matches the Secret object in the namespace:++```terminal|command=1|title=bash+kubectl get secrets --namespace api+NAME                  TYPE+api-token-ttr8q       kubernetes.io/service-account-token+default-token-vppc9   kubernetes.io/service-account-token+```++However, any workload that can read a secret in a namespace can also read the service account tokens in the same namespace.++In other words, you could have any other Pod using the same Service Account to authenticate against the Kubernetes API — effectively impersonating someone else.++Unfortunately, there's no mechanism to restrict access to a subset of Secrets in a namespace.++**The application has access to all of them, or none of them.**++### 2. The tokens associated with a Service Account are long-lived and do not expire++In other words, once you have access to one of them, you can use it forever (or until the administrator deletes the secret associated with the token).++### 3. No audience binding of the tokens++As a cluster administrator, you cannot associate a token with a specific audience.++Anyone with access to the service account token can authenticate itself and are authorized to communicate with any other service running inside the cluster.++The destination service doesn't have any way to verify whether the token it was presented with was meant for itself at all.++Tokens associated with Service Accounts are verified by the Kubernetes API.++In particular, there's a specific component in charge of validating and rejecting them: the **Token Review API**.++Let's manually create a token and validate it against the Token Review API.++### Creating a Service Account++Consider the following YAML manifest to create a namespace, `test` and a service account, `sa-test-1` in it:++```yaml|title=sa.yaml+apiVersion: v1+kind: Namespace+metadata:+  name: test+---+apiVersion: v1+kind: ServiceAccount+metadata:+  name: sa-test-1+  namespace: test+```++Save the above into a file `sa.yaml` and run kubectl apply:++```terminal|command=1|title=bash+kubectl apply -f sa.yaml++namespace/test created+serviceaccount/sa-test-1 created+```++To view the token associated with the service account:++```terminal|command=1|title=bash+kubectl --namespace test describe sa sa-test-1+Name:            	sa-test-1+Namespace:       	test+Labels:          	<none>+Annotations:     	kubectl.kubernetes.io/last-applied-configuration:+            {"apiVersion":"v1","kind":"ServiceAccount","metadata":+           {"annotations":{},"name":"sa-test-1","namespace":"test"}}+Image pull secrets:  <none>+Mountable secrets:   sa-test-1-token-99l5r+Tokens:          	sa-test-1-token-99l5r+Events:          	<none>+```++Then to view the secret object:++```+kubectl --namespace test describe secret sa-test-1-token-99l5r+Name:     	sa-test-1-token-99l5r+Namespace:	test+Labels:   	<none>+Annotations:  kubernetes.io/service-account.name: sa-test-1+          	kubernetes.io/service-account.uid: d2d210d8-8bd6-4115-b796-5ff4bd373d74++Type:  kubernetes.io/service-account-token++Data+====+ca.crt: 	1066 bytes+namespace:  4 bytes+token:  	eyJhbGciOiJSUzI1NiIsImtpZCI6InY3MDRITGNmdGt1WTdwNFk4Q2Y1Q0tTUm+5TMzdOVDBGdXFEQkU1bWVibE0ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW+50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJ0ZXN0Iiwi+a3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InNhLXRlc3QtMS+10b2tlbi05OWw1ciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1+hY2NvdW50Lm5hbWUiOiJzYS10ZXN0LTEiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2Nvd+W50L3NlcnZpY2UtYWNjb3VudC51aWQiOiJkMmQyMTBkOC04YmQ2LTQxMTUtYjc5Ni01Zm+Y0YmQzNzNkNzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6dGVzdDpzYS10ZXN0+LTEifQ.hJVpGWU4gd1VoDPaeHPT-fIS_1Uc_r_hhuLPw0AjdCownGmeZj-yv_GgItRvDK+dyj7jSpTnPfLiH0z8e_xGXssGHaWhHm5AOZt1Mf9TZYqdFrfNPdjwW2-_dpkytYC1zSVG+NMQsEAI758s3RRGezk24Js3zWjpStK1AlcnDOmFslNP1aI2RmlubGd9CKb9Nm_1ln4gVc+8n02RvpvlHU5LE6uVOe-e9TZrFpHrhPBDhrrFxC-x0-PgrdAlekc8wE2OcKfZtSsHofj+H_0MPcN94ethCmgwniBJMfGvxrMp8-6KkSSAhLMrdsHth_KiXtNkC6EZjFCAcAJKe6juu1OIrg+```++The `token` object in the Data is a base64 encoded object representing a JSON web token payload.++Once you have an appropriate RoleBinding or ClusterRoleBinding setup, you can then provide this token to perform operations in the cluster from within a pod.++For example, given a service account token, you want to verify whether the token is valid or not by invoking the Kubernetes TokenReview API.++### Verifying a token using TokenReview API++A Service Account is just an identity with no permissions associated with it.++If you want to grant access to the Service account you need two more objects: a binding and a role.++In the role you define access to the resources such as read-only access to Secrets or only GET, DESCRIBE and LIST operations on Pods.++Kubernetes comes with a list of roles prepackaged that you can list with:++```terminal|command=1|title=bash+kubectl get roles+```++In the following example, you will use the `system:auth-delegator` role which has all the permission you need to call the Token Review API. You can inspect it with:++```terminal|command=1|title=bash+kubectl get role system:auth-delegator+```++The only part missing is the binding.++You can create a ClusterRoleBinding to link the Service Account to a role and grant the permission cluster wide:++```yaml|title=sa_rbac.yaml+kind: ClusterRoleBinding+metadata:+  name: role-tokenreview-binding+  namespace: test+roleRef:+  apiGroup: rbac.authorization.k8s.io+  kind: ClusterRole+  name: system:auth-delegator+subjects:+- kind: ServiceAccount+  name: sa-test-1+  namespace: test+```++Save the above into a new file, sa_rbac.yaml and run kubectl apply:++```+kubectl apply -f sa_rbac.yaml+clusterrolebinding.rbac.authorization.k8s.io/role-tokenreview-binding created+```++You have now created a service account and associated it with a ClusterRole to allow it to invoke the TokenReview API.++How should you use it? Here's one way:++1. You could assign the Service Account to a Pod.+1. Invoke a HTTP client in that Pod to query the TokenReview API (You should be able to query the API because you assigned the `system:auth-delegator` role). When  making the request, you will pass on the service account token associated with the pod as a header value to the TokenReview API.+1. You will verify the same token that you are using to authenticate. It's an artificial scenario but it solves our purpose here.++The image you will use to create the pod needs to have the bash, curl and the sleep programs available.++You can use the image `amitsaha/curl` - which I created for this article and is available on Docker Hub.++```terminal|command=1|title=bash+kubectl run --namespace=test --serviceaccount=sa-test-1 --generator=run-pod/v1 \+  curl --image=amitsaha/curl  --image-pull-policy=Never --restart='Never' --command -- sleep 3600+pod/curl created+```++Now, run kubectl describe to show details about the pod that was just created:++```terminal|command=1|title=bash+kubectl --namespace test describe pod curl+Name:     	curl+Namespace:	test+..+Containers:+  curl:+	Container ID:  docker://9dc09c2f6f78b54e600eaec10db0885bad3da455126ab9230ac1914a301f445e+	Image:     	amitsaha/curl+	Image ID:  	docker://sha256:db3743f4dce44c902e0b89382d96d78ccf6adee92116cbfdb0c713591d0b08a8+	Port:      	<none>+	Host Port: 	<none>+	Command:+  	sleep+  	3600+	State:      	Running+  	Started:  	Fri, 18 Sep 2020 17:06:22 +1000+	Ready:      	True+	Restart Count:  0+	Environment:	<none>+	Mounts:+  	/var/run/secrets/kubernetes.io/serviceaccount from sa-test-1-token-smgh4 (ro)+..+```++The key information in the above output is that the service account token is available to the pod in the directory, `/var/run/secrets/kubernetes.io/serviceaccount`.++When a Pod is created, the Service Account data is automatically mounted as a volume and the Service Account token is available as a file inside that directory.++Let's retrieve the token.++Use kubectl exec to start a shell session inside the running pod:++```terminal|command=1|title=bash+kubectl --namepsace test exec -ti curl bash+root@curl:/#+```++Inside the shell session, first export a few variables.++First up, let's export the APISERVER variable pointing to the Kubernetes API:++```terminal|command=1|title=bash+# APISERVER=https://kubernetes.default.svc+```++The SERVICEACCOUNT variable points to the filesystem directory at which the service account related files can be found:++```terminal|command=1|title=bash+# SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount+```++The NAMESPACE variable contains the namespace obtained via reading the contents of the namespace file in the above directory:++```terminal|command=1|title=bash+# NAMESPACE=$(cat ${SERVICEACCOUNT}/namespace)+```++The TOKEN variable contains the service account token obtained via reading the contents of the token file in the same directory:++```terminal|command=1|title=bash+# TOKEN=$(cat ${SERVICEACCOUNT}/token)+```++The CACERT variable points to the Certificate Authority bundle that curl will use to verify the Kubernetes API certificate:++```terminal|command=1|title=bash+# CACERT=${SERVICEACCOUNT}/ca.crt+```++Let's issue a request to the Kubernetes API and see if you can authenticate:++```terminal|command=1|title=bash+curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api+{+  "kind": "APIVersions",+  "versions": [+  "v1"+  ],+  "serverAddressByClientCIDRs": [+  {+    "clientCIDR": "0.0.0.0/0",+    "serverAddress": "172.17.0.3:8443"+  }+  ]+}+```++Excellent, you can reach the Kubernetes API.++Note how you passed the Authorization header containing the service account token.++If you don't supply it or pass in an invalid token, you will get a HTTP 403 error response as follows:++```terminal|command=1|title=bash+curl --cacert ${CACERT} -X GET ${APISERVER}/api+{+  "kind": "Status",+  "apiVersion": "v1",+  "metadata": {},+  "status": "Failure",+  "message": "forbidden: User \"system:anonymous\" cannot get path \"/api\"",+  "reason": "Forbidden",+  "details": {},+  "code": 403+}+```++Next, you will see how you can invoke the `TokenReview API` to verify a service account token.++### Sending a token verification request++To issue a request to the TokenReviewAPI, you need two parts:++1. The API endpoint that you should call which is `/apis/authentication.k8s.io/v1/tokenreviews`.+1. A payload with the information about the token that you wish to validate.++The API endpoint expects a POST request with a JSON formatted payload of the following form:++```json+{+  "kind": "TokenReview",+  "apiVersion": "authentication.k8s.io/v1",+  "spec": {+  "token": "<your token>"+  }+}+```++In this case, the token you will use to authenticate to the API server as well as verify the status+of is the same. Thus, the curl command to run in the pod shell session is:

@danielepolencic Consider the the 2nd demo - where the secret store is going to verify whether the token presented to it via the calling service (API) is legit or not. The secret store uses its own SA token to authenticate itself to the API when it makes a TokenReview request to validate the API token. In that case, the token being verified is different from the token being used to authenticate itself.

amitsaha

comment created time in 11 days

PR opened learnk8s/learnk8s.io

Removed typo
+1 -1

0 comment

1 changed file

pr created time in 11 days

issue openedlearnk8s/kubernetes-production-best-practices

Clarify "Liveness probes values aren't the same as the Readiness"

In Liveness probes values aren't the same as the Readiness:

  • The title suggests "values"
  • The text body speaks about "endpoint":

When Liveness and Readiness probes are pointing to the same endpoint, the effects of the probes are combined.

I think the title is correct, and the task body should be updated to reflect that it's generally fine to have the same endpoint called from liveness and readiness probes, as long as the values are different (and those for liveness are more tolerant than those for readiness).

Referenced article Liveness probes are dangerous:

if you use Liveness Probe, don’t set the same specification for Liveness and Readiness Probe

  • you can use a Liveness Probe with the same health check, but a higher failureThreshold (e.g. mark as not-ready after 3 attempts and fail Liveness Probe after 10 attempts)

created time in 12 days

pull request commentlearnk8s/learnk8s.io

Article: Authenticating microservices requests in Kubernetes

@danielepolencic it looks like you have made most of the changes you were thinking of - I made a few more edits.

I am not sure why the article isn't showing up in the preview.

amitsaha

comment created time in 13 days

more