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

Securing kubernetes-ro use cases #5921

Closed
erictune opened this issue Mar 25, 2015 · 23 comments
Closed

Securing kubernetes-ro use cases #5921

erictune opened this issue Mar 25, 2015 · 23 comments
Labels
area/security kind/design Categorizes issue or PR as related to design. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle.
Milestone

Comments

@erictune
Copy link
Member

We'd like all communications to the apiserver to be over https and with authorization.
Kubernetes-ro does not meet these standards.

This bug is about things that use the kubernetes-ro service or the KUBERNETES_RO_* env vars.
kube-proxy is discussed separately in #5917 since it explicitly uses port explicitly 7080 and has a straightforward fix.

Existing Uses

Use cases for kubernetes-ro

  1. cluster/addons/dns/kube2sky/kube2sky.go
  2. cluster/addons/fluentd-elasticsearch/logging-demo/README.md
  3. examples/cassandra/java/io/k8s/cassandra/KubernetesSeedProvider.java
  4. examples/phabricator/cloudsql-authenticator/run.sh
  5. examples/rethinkdb/image/run.sh
  6. examples/rethinkdb/image/run.sh
  7. contrib/for-tests/network-tester/webserver.go
  8. users have said they use kubernetes-ro.

Backwards Compatibile or Breakage?

In order to make this be https, we have to break some uses cases, because some existing use cases assume it is http. So, we could either have a breakage day, or have it be configurable at cluster setup time, and just move GCE/GKE to the https option. The latter seems expedient but it would force some code like kube2sky and elasticsearch to handle both options. Better to just break it.

Decision: breakage.

Credential distribution

We need to distribute credentials to clients. The use cases are in pods, so we need a way to distribute credentials to all pods that need them. Credentials would probably be in the form of a kubernetes_auth file.

We could use secrets to distribute the kubernetes_auth files. This does make some of the pod descriptions quite a bit mode verbose. But we can address that later using service accounts or config templates/expansions.

credential creation

  1. In the place where we create a "kubelet" token, also create a token for user "readonlyuser".
  2. Put this token into a kubernetes_auth file.
  3. Put the kubernetes_auth file along with the master's certificates into a secret object.
  4. Post this secret to the master in cluster/saltbase/salt/kube-addons/kube-addons.sh.

credential use

  1. Change all pods that currently reference kubernetes-ro/KUBERNETES_RO to have a secret volume source.
  2. Change all the go code that references KUBERNETES_RO to instead take a --kubernetes_auth flag.
  3. change the java code and shell code to extract master address and the auth token and the certs from the kubernetes_auth file and use https.
  4. change all the shell code that uses KUBERNETES_RO and curl to extract the auth token from the kubernetes_auth

Cleanup

  1. Stop advertising kubernetes-ro service (remove from pkg/master/publish.go)
  2. fix docs to never speak of it again.

As an initial step, every cluster should be built with a secret with user readonly-user

Alternative

Run a proxy on each node which listens on each netns's localhost address, or one some other address visible to all netnses. Listen for http. Proxy via HTTPS to the master. See #2209

Advantages:

  • no credentials to distribute to pods, and to perhaps be compromised
  • no verbosity in pods for the secret volume source
  • no breakage for users
    Disadvantages:
    • fixing urls in proxies
    • unforseen complexity with proxying.
    • uses a special mechanism for kubernetes auth, instead of the the more general option we expect users to use (Secrets).
    • more moving parts. more magic, instead of well-understood, composable mechanisms.
@erictune erictune added this to the v1.0 milestone Mar 25, 2015
@erictune erictune added team/cluster sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle. labels Mar 25, 2015
@derekwaynecarr
Copy link
Member

@deads2k - I thought we were trying to get rid of kubernetes_auth files ;-)

@derekwaynecarr
Copy link
Member

@LiGgit - FYI

@deads2k
Copy link
Contributor

deads2k commented Mar 26, 2015

.kubeconfig files can be made portable so they could serve the same purpose. Using .kubeconfig files means that they can be manipulated and inspected using the command line tooling we have already developed. They also make it easy for users to be sure that the credentials they are going to provide to pods have the permissions they expect. The user simply creates the .kubeconfig file and runs the normal osc commands with the --kubeconfig flag.

I know there's been some difficulty understanding the merge order and the like, but a single self-container .kubeconfig file that holds all the secrets with a single set of entries isn't too bad to reason about.

@thockin
Copy link
Member

thockin commented Mar 27, 2015

Do we really need breakage? Can't we just define a different port or
service and deprecate kubernetes_ro?

On Thu, Mar 26, 2015 at 1:56 PM, David Eads notifications@github.com
wrote:

.kubeconfig files can be made portable so they could serve the same
purpose. Using .kubeconfig files means that they can be manipulated and
inspected using the command line tooling we have already developed. They
also make it easy for users to be sure that the credentials they are going
to provide to pods have the permissions they expect. The user simply
creates the .kubeconfig file and runs the normal osc commands with the
--kubeconfig flag.

I know there's been some difficulty understanding the merge order and the
like, but a single self-container .kubeconfig file that holds all the
secrets with a single set of entries isn't too bad to reason about.


Reply to this email directly or view it on GitHub
#5921 (comment)
.

@roberthbailey
Copy link
Contributor

Another alternative: Instead of creating a proxy on each node, create a proxy that we build into a docker image that can (optionally) be deployed in a pod along with a service that exposes a read-only http endpoint. This gives folks an easy transition path from http -> https but makes the default cluster installation only use secure communications to the master.

@roberthbailey
Copy link
Contributor

@liggitt FYI (take 2, hopefully spelled correctly this time)

@erictune
Copy link
Member Author

@cjcullen and anyone else following along:

Make secrets at cluster startup. #5470 is in.
That creates the following user accounts, which are relevant to this Issue:

  • system:logging
  • system:monitoring
  • system:dns

It also makes secrets at cluster startup in the default namespace with names:

  • token-system-logging
  • token-system-monitoring
  • token-system-dns

You can see these if you start a cluster and then kubectl get secrets token-system-logging, etc.

So, dns needs to use the token-system-dns token and talk to the apiserver on port 6443, rather than using 7080. The code that sets up its client is in cluster/addons/dns/kube2sky/kube2sky.go.
So:

  1. change newKubeClient in cluster/addons/dns/kube2sky/kube2sky.go to read a kubeconfig file. Follow the example in Use kubeconfig in several components #6969.
  2. change the pod definition, at cluster/addons/dns/skydns-rc.yaml.in, so that the pod has a secret volume and the kube2sky container mounts that volume and has an argument to read the kubeconfig file.

Then, do the same for cluster/addons/fluentd-elasticsearch/... with the token-system-logging.

Then, decide if it is worthwhile to do:

  • examples/cassandra/java/io/k8s/cassandra/KubernetesSeedProvider.java
  • examples/phabricator/cloudsql-authenticator/run.sh
  • examples/rethinkdb/image/run.sh
  • examples/rethinkdb/image/run.sh
  • contrib/for-tests/network-tester/webserver.go

If we don't change those, the demos won't work on on a system without port 7080.

We maybe don't need to use a different token for every component. We could just define a "default pod user", and make a token for that user, and use that token in all of the above examples.

@cjcullen
Copy link
Member

#7154 updated skydns/kube2sky to use port 6443 w/ the token-system-dns.

I'm taking a look at fluentd/elasticsearch now.

@cjcullen
Copy link
Member

It looks like fluentd/elasticsearch doesn't actually use kubernetes-ro. Am I missing something?

@erictune
Copy link
Member Author

I can't find fluend/elasticsearch either now.

@erictune
Copy link
Member Author

@vishh changed heapster to support kubernetes_auth files. https://github.com/GoogleCloudPlatform/heapster/pull/232/files
But then I settled on kubeconfig format instead.
So, heapster needs to change again.

@vishh
Copy link
Contributor

vishh commented Apr 23, 2015

@erictune: Here is the heapster logic that I was hoping would handle secrets.

@etune
Copy link

etune commented Apr 24, 2015

@vishh You really want @erictune, not @etune. He seems a lot smarter than me.

@cjcullen
Copy link
Member

For the examples that use KUBERNETES_RO, would it make sense to create a readonly user/token pair? We'd need to get the policy right to block that user from reading other secrets...

#7101 might make this easier: If we had service accounts, we could just have demos create a "my-demo-sa" service account, and then create a pod that used that service account.

@roberthbailey roberthbailey added the priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. label Apr 27, 2015
@erictune
Copy link
Member Author

@vishh since you made that change, we moved the bar, so another PR is needed.

@erictune
Copy link
Member Author

@cjcullen in response to your previous comment, I filed a more detailed proposal, #7444

@gmarek
Copy link
Contributor

gmarek commented May 11, 2015

How it relates to #4567?

@lavalamp
Copy link
Member

@gmarek this is a prereq for #4567.

@erictune
Copy link
Member Author

@lavalamp @cjcullen

"Readonly" isn't actually a particularly useful protection since you can read a secret that contains a credential for accessing in a readwrite fashion.

So, I suggest that we deprecate the readonly port, and just use the per-namespace default service account (#7101) as the way to access the apiserver in all examples and contribs. We can leave it unspecified what permissions this account has (currently read-write, but evolving once the Policy feature is merged).

@lavalamp
Copy link
Member

@erictune SGTM-- and since #7101 has merged I can get right to it.

@thockin thockin added kind/design Categorizes issue or PR as related to design. and removed kind/design Categorizes issue or PR as related to design. priority/design labels May 19, 2015
@lavalamp
Copy link
Member

lavalamp commented Jun 4, 2015

I'm gonna say that #9233 will fix this; there may be more, but this is the last piece I'm aware of.

@alex-mohr
Copy link
Contributor

Looks like #9233 merged. @erictune @lavalamp to sanity check where we are and whether this is now closable?

@lavalamp
Copy link
Member

lavalamp commented Jun 5, 2015

I think this is fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/security kind/design Categorizes issue or PR as related to design. priority/important-soon Must be staffed and worked on either currently, or very soon, ideally in time for the next release. sig/cluster-lifecycle Categorizes an issue or PR as relevant to SIG Cluster Lifecycle.
Projects
None yet
Development

No branches or pull requests