-
Notifications
You must be signed in to change notification settings - Fork 7.3k
Pass user authentication to Tiller #1932
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
Conversation
Thanks for your pull request. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). 📝 Please follow instructions at https://github.com/kubernetes/kubernetes/wiki/CLA-FAQ to sign the CLA. Once you've signed, please reply here (e.g. "I signed it!") and we'll verify. Thanks.
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
I signed it! |
@technosophos , here are few issues:
|
I think we should probably disallow both |
I put this onto 2.3.0 and marked it WIP so it doesn't actually get merged into 2.2.0 |
I signed it! |
f8b8cee
to
d1d3bc0
Compare
@technosophos do you mind taking a first pass at this pr. If the general structure looks ok, we can write unit tests. We have a follow up pr to add authZ check. appscode#10 |
This will definitely need some documentation, but things are looking good. I am going to do some manual testing today. |
Just curious. How come the "Released By" field doesn't get populated by default with "admin" on a cluster with no users/roles (RBAC not set up)? |
@michelleN , what are you seeing in such a cluster? What type of of auth are you using (basic/bearer/client cert)? |
@tamalsaha I'm using client cert |
Hi, any comments on the code? |
pkg/tiller/server.go
Outdated
caCert, _ := getCertificateAuthority(md) | ||
|
||
// ref: k8s.io/helm/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util#NewFactory() | ||
flags := pflag.NewFlagSet("", pflag.ContinueOnError) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you remove all calls to pflags
pkg/tiller/server.go
Outdated
md, _ := metadata.FromContext(ctx) | ||
token := md[string(helm.Authorization)][0][len("Bearer "):] | ||
|
||
apiServer, err := getServerURL(md) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why would there be a different server url for the user?
pkg/tiller/server.go
Outdated
flagNames.ClusterOverrideFlags.APIServer.ShortName = "s" | ||
|
||
clientcmd.BindOverrideFlags(overrides, flags, flagNames) | ||
tokenConfig, err := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin).ClientConfig() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't want to use an interactive loader in the server
pkg/helm/option.go
Outdated
) | ||
} | ||
|
||
func extractKubeConfig() map[string]string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pkg/helm should not parse kubeconfig, it should be passed into the context from cmd/helm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a function that reads the config at https://github.com/kubernetes/helm/blob/master/cmd/helm/helm.go#L238-L250
pkg/helm/option.go
Outdated
} | ||
|
||
// Kube APIServer URL | ||
if len(c.Host) != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think host is required, tiller already has it
pkg/helm/option.go
Outdated
configData[string(K8sClientCertificate)] = base64.StdEncoding.EncodeToString(c.TLSClientConfig.CertData) | ||
} | ||
|
||
if len(c.TLSClientConfig.CAFile) != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tiller already has the CA file
pkg/tiller/server.go
Outdated
ctx = context.WithValue(ctx, helm.K8sUser, user) | ||
ctx = context.WithValue(ctx, helm.K8sConfig, kubeConfig) | ||
|
||
// TODO: Remove |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this needs to be removed
pkg/tiller/server.go
Outdated
|
||
func checkBearerAuth(ctx context.Context) (*authenticationapi.UserInfo, *rest.Config, error) { | ||
md, _ := metadata.FromContext(ctx) | ||
token := md[string(helm.Authorization)][0][len("Bearer "):] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to be checked before accessing to avoid panics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR seems to reproduce lots of stuff that's already in either Kubernetes or in Helm. Some of it appears to be copied verbatim from Kubernetes. It looks to me like it could be significantly simplified.
pkg/helm/option.go
Outdated
func extractKubeConfig() map[string]string { | ||
configData := make(map[string]string) | ||
clientConfig := cmdutil.DefaultClientConfig(pflag.NewFlagSet("", pflag.ContinueOnError)) | ||
c, err := clientConfig.ClientConfig() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just clean c
of fields we don't want, serialize it to JSON, and then send that instead of creating a whole bunch of different headers? That would simplify both the marshal and unmarshal operations for this data.
gRPC will even base64 encode/decode this for you if you suffix the header -bin
. https://godoc.org/google.golang.org/grpc/metadata#New
@@ -0,0 +1,32 @@ | |||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should be named auth-header.go
, not types.go
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
auth_header.go
//AuthHeader is key type for context | ||
type AuthHeader string | ||
|
||
const ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If these are used by both the client and the server, they probably shouldn't be in the client package. That requires importing the client package for the server.
md, ok := metadata.FromContext(ctx) | ||
if !ok { | ||
return nil, errors.New("Missing metadata in context.") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems really complicated for what you are trying to do. Why not construct a single client config object and just run a client.DiscoveryClient.ServerVersion()
? Wouldn't that just let the client library do most of what you do in the multiple functions below? This would be even easier if you sent a sanitized client config instead of storing various bits of the client config in different gRPC headers.
bca5a06
to
f2a19a8
Compare
@technosophos @adamreese PTAL. All comments are addressed. |
cmd/helm/installer/uninstall.go
Outdated
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" | ||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" | ||
|
||
"k8s.io/helm/pkg/kube" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be moved back. It's a local package.
Typical best practices for go imports are
- stdlib
- dependencies
- local packages
go fmt
would agree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bacongobbler , gofmt is ok with things as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tamalsaha run goimports
to group them correctly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adamreese I just ran:
$ goimports -w cmd
$ goimports -w ./cmd/..
$ goimports -w ./pkg/..
$ goimports -w pkg
Still no change. In fact that suggests changes some other unrelated files:
modified: pkg/chartutil/load.go
modified: pkg/releaseutil/filter_test.go
modified: pkg/releaseutil/sorter_test.go
So, I skipped those.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, it seems like they don't really care about import ordering. Still, the precedence for packages being sorted in this order has always been implied. See cmd/helm/init.go (and anywhere else in the source code) for an example. It's just best practices we've been following.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never heard of this best practice. But if project follows unwritten best practices regarding style, I'm happy to oblige. Just thought I was done with these, when I switched to writing GO. :)
pkg/tiller/server.go
Outdated
"google.golang.org/grpc/peer" | ||
"k8s.io/helm/pkg/kube" | ||
"k8s.io/helm/pkg/version" | ||
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here RE: package imports
cmd/helm/installer/uninstall.go
Outdated
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" | ||
|
||
"k8s.io/helm/pkg/kube" | ||
"k8s.io/kubernetes/pkg/api" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this got accidentally shifted over (third-party package from kubernetes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
010e821
to
8035389
Compare
@michelleN , it seems that GKE does not support TokenReview api even with alpha features enabled in 1.5.6 cluster. |
@adamreese / @technosophos , to test this manually, deploy this tiller. Then install a new chart using helm build from this pr. Then list releases. You should see the deployer name.
|
22b62ec
to
3b43607
Compare
I have added checks to dynamically check if TokenReview api is not enabled. I don't get the error in GKE any more. Obviously, you will not see the username in GKE. |
This should be unblocked again at this point. We've merged in gRPC 1.2. |
Bumping to 2.5.0, since it still needs rebasing. |
Refactor is done. This issue is unblocked. |
Any movement on this happening? |
Rebased. |
Do you intend to take group membership into account as well? I see treatment of "user names" in the proposed changes here in file pkg/tiller/server.go we're omitting the groups that you can extract from the "Organization" AVAs in the certificate's subject. |
crt := tlsInfo.State.VerifiedChains[0][0] | ||
user := authenticationapi.UserInfo{ | ||
Username: crt.Subject.CommonName, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- What about using
crt.Subject.Organization
here to populate theUserInfo
"Groups" field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Group name needs to be preserved for TokenReview calls. But I believe this was not next working at Kube 1.5, when I originally wrote this pr.
@seh, do you mind pointing how Kubectl is handling Group names from crt these days? I thin we need to parse the same way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The authentication documentation on X.509 client certificates is here.
As of Kubernetes 1.4, client certificates can also indicate a user’s group memberships using the certificate’s organization fields. To include multiple group memberships for a user, include multiple organization fields in the certificate.
In my clusters, we write most of our RBAC bindings against groups, not users, so honoring the group membership expressed in the certificates' "O" AVAs is important for us.
@technosophos, it seems that I won't be able to find time to work through the review process. I am sad that it turned out this way. I don't want to hold off this feature from Helm users. So, I am closing this pr. Core team / interested parties are welcome to work through the review process based on this pr. |
First step for #1918