kelseyhightower / vault-controller

Automate the creation of unique Vault tokens for Kubernetes Pods using init containers.
Apache License 2.0
447 stars 69 forks source link

Proposal: Design for a more secure interaction #4

Open khenidak opened 7 years ago

khenidak commented 7 years ago

Right now the dependancies is on pod name to validate pod. Pods can mistakenly or maliciously use wrong names, more over people will use partially trusted code (i.e. layers of containers images, libraries and so forth). These things may load wrong names.

Proposal:

  1. Use ambassador pattern, each pod contributing to this needs to run a simple container that talks to the vault on behalf of the pod.
  2. The ambassador communicates with vault using client cert.
  3. The ambassador is the one that looks up pod name.
  4. The ambassador exposes a simple rest api locally to the pod. this is a proxy api to the actual vault.

Additional future features can be added to the ambassador, offloading common functions such as token validation, token renewal etc.

kelseyhightower commented 7 years ago

@khenidak Even if the pod uses the wrong, we still look up the pod in the API from a intermediate controller (vault-controller) running in the cluster, which looks up the Pod info from the Kubernetes API server, and only issues a one time use token to the Pod based on the annotations defined by the administrator. The Pod can only ask for this process to take place. We then call the Pod based on the Pod IP address return by Kubernetes. This is written up in the how this works section.

So the vault-controller seems to play the ambassador here. The Pod uses an init-container to kick the ambassador, which does steps 2- 3, and calls the init container back on an API using the IP address obtained from Kubernetes, not the Pod.

kelseyhightower commented 7 years ago

Also loading the wrong name would cause the vault-controller to look up either a Pod that does not actually exist, which means no token will be generated, and if the Pod does exist it will validate the annotations of the Pod as returned by Kubernetes, and does not trust the Pod that initiated the original request. We are trusting the Kubernetes API and the administrators desired state. The token is then send to the IP address based on the information in the Kubernetes API, not the info submitted by the Pod. If this is a different Pod than the calling Pod, the original Pod still does not get a token.

kelseyhightower commented 7 years ago

@khenidak Did you see what we are actually doing here? We are using an "helper" container called vault-init that pulls the Pod name from the Kubernetes downward API, and initiates the flow outlined above and in the How it works doc.

Albibek commented 7 years ago

Hi. I can see more security flaw in the interaction model: Vault policy name is specified client side. So user that creates pod can specify another policy and get secrets that are probably allowed only to other pods, which the user originally does not have access. This includes policy of the vault-contoller itself. Proposal: remove policy annotation and generate policy name based on only data known to kubernetes. Third-party resources come in mind as a solution, because their usage can be easily limited by user-based policies. Partcular users can be prohibited to use TPR, while limiting annotations is harder.