Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use kubernetes secrets for passing sensitive environment variables to pods #398

Open
elgalu opened this issue Mar 26, 2020 · 9 comments
Open

Comments

@elgalu
Copy link

elgalu commented Mar 26, 2020

Update by @consideRatio

The environment variable should in order to follow common k8s security practices be mounted from a k8s Secret rather than set directly as a name/value pair in the k8s Pod resource manifest.

# like this...
spec:
  containers:
  - name: users-jupyter-server-container
    env:
      - name: JUPYTERHUB_API_TOKEN
        valueFrom:
          secretKeyRef:
            name: user1-jupyterhub-api-token
            key: JUPYTERHUB_API_TOKEN
# instead of liket his
spec:
  containers:
  - name: users-jupyter-server-container
    env:
      - name: JUPYTERHUB_API_TOKEN
        value: secret-stuff

The difference is that if you do kubectl get pod -o yaml jupyter-user1 then you will see the secret-stuff value if we mount it like we do now, but not if we reference a k8s Secret in order to mount the environment variable. But, for a user with ability to do kubectl get secret -o yaml user1-jupyterhub-api-token then it doesn't matter I think.

Original issue text

env = super(KubeSpawner, self).get_env()

https://github.com/jupyterhub/jupyterhub/blob/914a3eaba5c83f639b4b5d8873c6e9d93e809f31/jupyterhub/spawner.py#L722

@consideRatio
Copy link
Member

consideRatio commented Oct 25, 2020

This relates a bit to #110. I think creating a k8s secret and mounting it to the user pod creates quite a bit of complexity to the deployment even though I know it is a practice to not expose a secret directly in the Pod resource manifest.

I'd like to understand the security implications a bit better. Is the security difference regarding that user with get permissions only k8s Pod resources but not k8s Secret resources will be able to get this information that is the security concern only, or is there more?

@consideRatio consideRatio changed the title Tokens should be put in kind: Secret instead of env vars JUPYTERHUB_API_TOKEN exposed by users with kubectl get pod permissions Oct 25, 2020
@tirumerla
Copy link

tirumerla commented Dec 2, 2020

Hi @consideRatio - I was also wondering about this today as i found two env. variables JUPYTERHUB_API_TOKEN & JPY_API_TOKEN when i did kubectl get pod -o yaml <singleuser_pod_name>. Here are my concerns with this approach

  • "Plain Text" env. variables don't have basic security measures like providing encryption at rest or having some sort of authorization policies just like k8s secrets do.
  • You can enforce policies/permissions by giving read-only access to pods but not secrets. Even if you want to give access to secrets you can have granular policies to give read-only access to specific secrets.

Would be great if we can use k8s secrets for these variables as opposed to "plain text" env. variables.

Thanks.

@yuvipanda yuvipanda changed the title JUPYTERHUB_API_TOKEN exposed by users with kubectl get pod permissions Use kubernetes secrets for passing sensitive environment variables to pods Dec 3, 2020
@yuvipanda
Copy link
Collaborator

This makes sense. The complexity here will be creating & cleaning up the secret objects with pod start / stop. We could explore doing this with kubernetes garbage collection, although since the secret would need to be created before the pod - not sure if that'll work for that.

We already create PVCs before creating pods, I think we can extend that logic to secrets. While we're there, we could possibly just put all env vars there instead of just 'sensitive' ones.

Happy to review any PRs :)

@minrk
Copy link
Member

minrk commented Dec 3, 2020

I think tackling this will give us a chance to generally improve logic around "objects created to go with the pod". Using consistent labels for any object created by kubespawner associated with a user pod should make it manageable to create and clean up everything without lifecycle concerns when e.g. gc is unavailable due to ordering.

@tirumerla
Copy link

Thanks @yuvipanda and @minrk for the response. This is currently a security concern for us, and would love to help. Unfortunately I'm not sure where to start, however I'll try helping as much as I can.

@yuvipanda
Copy link
Collaborator

https://github.com/jupyterhub/kubespawner/blob/master/kubespawner/spawner.py#L1898 is probably the place to look. We are creating a PVC before starting the pod if needed, so we can attach the PVC to the pod. Same way, we could create a secret and attach it to the pod. https://github.com/jupyterhub/kubespawner/blob/master/kubespawner/spawner.py#L1911 fetched the pod manifest, and we could put the secret binding in there.

We pass env vars to the pod spec from around https://github.com/jupyterhub/kubespawner/blob/master/kubespawner/spawner.py#L1453, so we'll need to modify that to bring in all env vars via secrets.

Hope this helps, @tirumerla!

@tirumerla
Copy link

Thanks @yuvipanda for the information. I will take a look.

@consideRatio
Copy link
Member

@yuvipanda

This makes sense. The complexity here will be creating & cleaning up the secret objects with pod start / stop. We could explore doing this with kubernetes garbage collection, although since the secret would need to be created before the pod - not sure if that'll work for that.

Actually, the secret can be created after, but the pod will be stuck in ContainerCreating state until the secret is available. Another option that may/may not work is to update the ownerRef of the Secret resource after having created the Pod, but I'm not sure that's allowed to be updated by k8s api-server or suitable from a robustness perspective.

@tirumerla
Copy link

Hi @yuvipanda - Apologies for the delay. I took a stab at it, let me know what you think about it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants