Skip to content

Conversation

tamalsaha
Copy link
Contributor

First step for #1918

@k8s-ci-robot
Copy link

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.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. label Feb 9, 2017
@tamalsaha
Copy link
Contributor Author

I signed it!

@tamalsaha
Copy link
Contributor Author

@technosophos , here are few issues:

@technosophos
Copy link
Member

I think we should probably disallow both impersonate and insecureSkipVerify.

@technosophos technosophos added this to the 2.3.0 milestone Feb 9, 2017
@technosophos
Copy link
Member

I put this onto 2.3.0 and marked it WIP so it doesn't actually get merged into 2.2.0

@saumanbiswas
Copy link

I signed it!

@k8s-ci-robot k8s-ci-robot added cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. and removed cncf-cla: no Indicates the PR's author has not signed the CNCF CLA. labels Feb 10, 2017
@tamalsaha
Copy link
Contributor Author

tamalsaha commented Mar 2, 2017

@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

@technosophos
Copy link
Member

This will definitely need some documentation, but things are looking good. I am going to do some manual testing today.

@technosophos technosophos requested review from michelleN and removed request for technosophos March 8, 2017 18:12
@michelleN
Copy link
Member

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)?

@tamalsaha
Copy link
Contributor Author

@michelleN , what are you seeing in such a cluster? What type of of auth are you using (basic/bearer/client cert)?

@michelleN
Copy link
Member

@tamalsaha I'm using client cert

@tamalsaha
Copy link
Contributor Author

Hi, any comments on the code?

caCert, _ := getCertificateAuthority(md)

// ref: k8s.io/helm/vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util#NewFactory()
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
Copy link
Member

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

md, _ := metadata.FromContext(ctx)
token := md[string(helm.Authorization)][0][len("Bearer "):]

apiServer, err := getServerURL(md)
Copy link
Member

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?

flagNames.ClusterOverrideFlags.APIServer.ShortName = "s"

clientcmd.BindOverrideFlags(overrides, flags, flagNames)
tokenConfig, err := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin).ClientConfig()
Copy link
Member

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

)
}

func extractKubeConfig() map[string]string {
Copy link
Member

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

}

// Kube APIServer URL
if len(c.Host) != 0 {
Copy link
Member

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

configData[string(K8sClientCertificate)] = base64.StdEncoding.EncodeToString(c.TLSClientConfig.CertData)
}

if len(c.TLSClientConfig.CAFile) != 0 {
Copy link
Member

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

ctx = context.WithValue(ctx, helm.K8sUser, user)
ctx = context.WithValue(ctx, helm.K8sConfig, kubeConfig)

// TODO: Remove
Copy link
Member

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


func checkBearerAuth(ctx context.Context) (*authenticationapi.UserInfo, *rest.Config, error) {
md, _ := metadata.FromContext(ctx)
token := md[string(helm.Authorization)][0][len("Bearer "):]
Copy link
Member

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

Copy link
Member

@technosophos technosophos left a 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.

func extractKubeConfig() map[string]string {
configData := make(map[string]string)
clientConfig := cmdutil.DefaultClientConfig(pflag.NewFlagSet("", pflag.ContinueOnError))
c, err := clientConfig.ClientConfig()
Copy link
Member

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 @@
/*
Copy link
Member

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.

Copy link
Member

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 (
Copy link
Member

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.")
}
Copy link
Member

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.

@tamalsaha
Copy link
Contributor Author

tamalsaha commented Mar 16, 2017

@technosophos @adamreese PTAL. All comments are addressed.

"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"

"k8s.io/helm/pkg/kube"
Copy link
Member

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

  1. stdlib
  2. dependencies
  3. local packages

go fmt would agree.

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Contributor Author

@tamalsaha tamalsaha Mar 16, 2017

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.

Copy link
Member

@bacongobbler bacongobbler Mar 16, 2017

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.

Copy link
Contributor Author

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. :)

"google.golang.org/grpc/peer"
"k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/version"
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
Copy link
Member

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

"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"

"k8s.io/helm/pkg/kube"
"k8s.io/kubernetes/pkg/api"
Copy link
Member

@bacongobbler bacongobbler Mar 16, 2017

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)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed.

@tamalsaha tamalsaha force-pushed the tiller-auth branch 2 times, most recently from 010e821 to 8035389 Compare April 10, 2017 16:32
@tamalsaha
Copy link
Contributor Author

tamalsaha commented Apr 10, 2017

@michelleN , it seems that GKE does not support TokenReview api even with alpha features enabled in 1.5.6 cluster.

@tamalsaha
Copy link
Contributor Author

tamalsaha commented Apr 10, 2017

@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.

$ helm install stable/redis
$ helm ls

# ./helm install stable/redis
NAME:   factual-lionfish
LAST DEPLOYED: Mon Apr 10 16:31:03 2017
NAMESPACE: default
STATUS: DEPLOYED
RELEASED BY: qacode.system-admin

RESOURCES:
==> v1/Secret
NAME                    TYPE    DATA  AGE
factual-lionfish-redis  Opaque  1     1s

==> v1/PersistentVolumeClaim
NAME                    STATUS   VOLUME  CAPACITY  ACCESSMODES  AGE
factual-lionfish-redis  Pending  1s

==> v1/Service
NAME                    CLUSTER-IP   EXTERNAL-IP  PORT(S)   AGE
factual-lionfish-redis  10.0.194.85  <none>       6379/TCP  1s

==> extensions/v1beta1/Deployment
NAME                    DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
factual-lionfish-redis  1        1        1           0          1s


NOTES:
Redis can be accessed via port 3306 on the following DNS name from within your cluster:
factual-lionfish-redis.default.svc.cluster.local

To get your password run:

    REDIS_PASSWORD=$(kubectl get secret --namespace default factual-lionfish-redis -o jsonpath="{.data.redis-password}" | base64 --decode)

To connect to your Redis server:

1. Run a Redis pod that you can use as a client:

   kubectl run factual-lionfish-redis-client --rm --tty -i --env REDIS_PASSWORD=$REDIS_PASSWORD --image bitnami/redis:3.2.8-r2 -- bash

2. Connect using the Redis CLI:

  redis-cli -h factual-lionfish-redis -a $REDIS_PASSWORD

root@qa-buildbox:~# ./helm ls
NAME               	REVISION	UPDATED                 	STATUS  	CHART      	NAMESPACE	RELEASED BY        
factual-lionfish   	1       	Mon Apr 10 16:31:03 2017	DEPLOYED	redis-0.5.1	default  	qacode.system-admin
fancy-chinchilla   	1       	Mon Apr 10 08:02:27 2017	DEPLOYED	redis-0.5.1	default  	                   
kissable-woodpecker	1       	Mon Apr 10 07:59:31 2017	DEPLOYED	mysql-0.2.5	default  	                   

@tamalsaha
Copy link
Contributor Author

I am told that GKE does not enable TokenReview in sig-apps. So, once auth is added Tiller will not work in GKE?

sig-app-tiller

@tamalsaha tamalsaha force-pushed the tiller-auth branch 5 times, most recently from 22b62ec to 3b43607 Compare April 13, 2017 13:57
@tamalsaha
Copy link
Contributor Author

tamalsaha commented Apr 13, 2017

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.

@technosophos
Copy link
Member

This should be unblocked again at this point. We've merged in gRPC 1.2.

@technosophos
Copy link
Member

Bumping to 2.5.0, since it still needs rebasing.

@technosophos
Copy link
Member

Refactor is done. This issue is unblocked.

@mattfarina
Copy link
Collaborator

Any movement on this happening?

@k8s-reviewable
Copy link

This change is Reviewable

@tamalsaha
Copy link
Contributor Author

Rebased.

@seh
Copy link
Contributor

seh commented Jun 20, 2017

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,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@tamalsaha tamalsaha Jun 20, 2017

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.

Copy link
Contributor

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.

@tamalsaha
Copy link
Contributor Author

@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.

@tamalsaha tamalsaha closed this Jun 25, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. feature in progress
Projects
None yet
Development

Successfully merging this pull request may close these issues.