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

Enable RBAC #86

Merged
merged 1 commit into from
Feb 13, 2018
Merged

Enable RBAC #86

merged 1 commit into from
Feb 13, 2018

Conversation

dzlier-gcp
Copy link
Contributor

@dzlier-gcp dzlier-gcp commented Feb 10, 2018

Enable RBAC, and create service accounts/roles/rolebindings for sidecar and controller as appropriate.

Currently this creates a service account in the default namespace for sidecar, and another for controller.

It then gives permission to sidecar to get and update GameServers, and access to events, pods, nodes, gameservers, and custom resource definitions for controller.

There are more permissions for controller here than we first discussed; I came by the list of resources and the access required for each by adding them one-at-a-time after the controller failed to start with error messages saying different access was required. Everything there now is needed for one reason or another.

Note: You may need to delete all running GameServers before installing this update, otherwise you may get stuck with GameServers that cannot be deleted.

Closes #57

@cyriltovena
Copy link
Collaborator

Looks good.

I think service account name are too generic and could easily clash with user service account especially on the default namespace. Should we prefix them with agones- ?

Another thought, should we pass the sidecar service account name as an environement variable to the controller ? I have a feeling that if they want to change the name they have to also re-compile the controller.

Also @markmandel should we create an issue for creating a helm chart to ease users installation ?

Copy link
Member

@markmandel markmandel left a comment

Choose a reason for hiding this comment

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

This is looking good - but I agree there should be some naming changes.

Also think there should be a rejig of where the service account gets applied.

See inline comments, but let me know if anything doesn't make sense.

build/Makefile Outdated
@@ -233,6 +233,7 @@ gcloud-auth-cluster: ensure-build-image
docker run --rm $(common_mounts) --entrypoint="gcloud" $(build_tag) config set compute/zone \
`grep zone: $(build_path)/gke-test-cluster/deployment.yml | sed 's/zone: //'`
docker run --rm $(common_mounts) --entrypoint="gcloud" $(build_tag) container clusters get-credentials $(CLUSTER_NAME)
docker run --rm $(common_mounts) $(build_tag) kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user $$(gcloud config get-value account)
Copy link
Member

Choose a reason for hiding this comment

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

let's put a - in front of this, as if you re-run this target, it will fail the second time, but I think it's best if it fails gracefully (as maybe you've already setup this before)

Context: https://www.gnu.org/software/make/manual/html_node/Errors.html

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was wondering if there was a way to do that, thanks. Done.

apiVersion: v1
kind: ServiceAccount
metadata:
name: sidecar
Copy link
Member

Choose a reason for hiding this comment

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

Agree with @Kuqd - this name is a bit generic.

I would change it all the sidecar names to agones-sdk (I previously changed the sidecar items to sdk, as what if we want more sidecars later on? Better to be explicit)

kind: ClusterRole
metadata:
namespace: default
name: sidecar
Copy link
Member

@markmandel markmandel Feb 10, 2018

Choose a reason for hiding this comment

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

Same as above agones-sdk (etc) - I won't mark them all, but just referencing the pattern.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

apiVersion: v1
kind: ServiceAccount
metadata:
name: controller
Copy link
Member

Choose a reason for hiding this comment

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

agones-controller across the board.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

@@ -192,9 +194,11 @@ func (gs *GameServer) FindGameServerContainer() (int, corev1.Container, error) {
// Pod creates a new Pod from the PodTemplateSpec
// attached for the
func (gs *GameServer) Pod(sidecars ...corev1.Container) (*corev1.Pod, error) {
podSpec := *gs.Spec.Template.Spec.DeepCopy()
podSpec.ServiceAccountName = SidecarServiceAccountName
Copy link
Member

Choose a reason for hiding this comment

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

Also agree with @Kuqd this should be an flag/env var that gets passed to the Controller (and maybe the 'sidecar' flag should be renamed to sdk ?) - see example

My current thought is the the Pod() method below should go back to how it was, and the controller should add the ServiceAccountName around here. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm all right with setting the sidecar account name as a flag (I considered that originally), but am curious when a user would want to be changing it?

Also why shouldn't we be setting the Pod's service account within the Pod() method? It sets everything else about its own metadata, spec, and containers. Don't we want to initialize everything about it in one place?

Copy link
Member

Choose a reason for hiding this comment

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

I could see a user having their own service accounts setup (down the line) and wanting to change the value. I think it should still have our own name as the default, but being able to have it able to be overwritten would be good.

Yeah, I'm going to rescind my idea to do the addition in the controller. For some reason I added the health checks in the controller - and I'm not sure why 😕 so yeah, leave it in gs.Pod()

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually now that I'm looking at this, I think it should be something that is specified in GameServer.Spec.Template.Spec (type PodSpec), instead of something that is overwritten manually here. Then it would go in the GameServer type creation yaml files, where a serviceAccountName field is allowed in the first place.

Copy link
Member

@markmandel markmandel Feb 12, 2018

Choose a reason for hiding this comment

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

I would say that it would be a case of - if it has been set in the pod template, then leave it alone. If it hasn't been set, then set it to our rbac value.

Then users can overwrite it if they so desire, but it has a sensible default. Which is pretty much what is done elsewhere. WDYT?

But both options are good to have as well - redefine it globally, but also be able to change it on a per-GameServer basis if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's fine, it's just a question of how to decide the default - should it still just be a constant in the types.go file? If we want it to be a value controlled from main.go, then it'll need to come in as a param value which means changing the signature.

I'd lean on having a constant that matches the default sidecar service account over having a flag, personally. If the user wants to modify the sidecar service account name (without rebuilding), then the way to do that would be to provide it in the definition file.

Copy link
Member

Choose a reason for hiding this comment

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

I'd lean on having a constant that matches the default sidecar service account over having a flag, personally. If the user wants to modify the sidecar service account name (without rebuilding), then the way to do that would be to provide it in the definition file.

Why don't we go this way for now, for simplicity sake - and if having the flag becomes something that users want, we can add it at a later date.

verbs: ["get"]
- apiGroups: ["stable.agones.dev"]
resources: ["gameservers"]
verbs: ["get", "list", "update", "watch"]
Copy link
Member

Choose a reason for hiding this comment

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

Super interesting to see all the actual permissions required.

@markmandel
Copy link
Member

@Kuqd A design ticket on whether helm/ksonnet or nothing at all is probably worth talking about.

I deliberately haven't gone down that path as it added extra complexity and tooling for the user to know about - but maybe we're at a point were we should look at it? It's worth the discussion at least.

build/Makefile Outdated
@@ -258,7 +259,7 @@ clean-gcloud-config:
# Switches to an "agones" profile, and starts a kubernetes cluster
# of the right version.
#
# Use MINIKUBE_DRIVER variable to change the VM driver
# Use MINIKUBE_DRIVER variable to change the VM driver
# (defaults virtualbox for Linux and OSX, hyperv for windows) if you so desire.
minikube-test-cluster: minikube-agones-profile
$(MINIKUBE) start --kubernetes-version v1.8.0 --vm-driver $(MINIKUBE_DRIVER)
Copy link
Member

Choose a reason for hiding this comment

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

From: https://kubernetes.io/docs/getting-started-guides/minikube/#examples

To set the AuthorizationMode on the apiserver to RBAC, you can use: --extra-config=apiserver.Authorization.Mode=RBAC.

So we should add the setting --extra-config=apiserver.Authorization.Mode=RBAC to the minikube-test-cluster script so that RBAC is enabled there as well.

minikube-test-cluster: minikube-agones-profile
	$(MINIKUBE) start --kubernetes-version v1.8.0 --vm-driver $(MINIKUBE_DRIVER) \
		--extra-config=apiserver.Authorization.Mode=RBAC

Copy link
Member

Choose a reason for hiding this comment

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

Don't add this yet - this seems to be what is causing the issue. I'll investigate.

@@ -204,6 +206,9 @@ func (gs *GameServer) Pod(sidecars ...corev1.Container) (*corev1.Pod, error) {
pod.ObjectMeta.Namespace = gs.ObjectMeta.Namespace
// Make sure these are blank, just in case
pod.ResourceVersion = ""
if len(pod.Spec.ServiceAccountName) == 0 {
Copy link
Member

Choose a reason for hiding this comment

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

Super nitpicky, but just for consistency's sake across the codebase, this should be:
if pod.Spec.ServiceAccountName != ""

Copy link
Member

Choose a reason for hiding this comment

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

Oh, and this really needs to be included in the tests for Pod() - make sure it's actually set.
https://github.com/googleprivate/agones/blob/master/pkg/apis/stable/v1alpha1/types_test.go#L151

@markmandel
Copy link
Member

Looks like the make gcloud-test-cluster failed on me on the last step:

build git:(feature/rbac) ✗ make gcloud-test-cluster mkdir -p ~/.kube mkdir -p /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud docker run --rm -it -v /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v /home/markmandel/workspace/agones/src/agones.dev/agones:/go/src/agones.dev/agones agones-build:0229fec933 gcloud \ deployment-manager deployments create test-cluster --config=/go/src/agones.dev/agones/build/gke-test-cluster/deployment.yml The fingerprint of the deployment is 2-LRaPoxhb4S6UenbRtrxg== Waiting for create [operation-1518478067241-5650c39cc1029-5858e97d-ea9c9db5]...done. Create operation operation-1518478067241-5650c39cc1029-5858e97d-ea9c9db5 completed successfully. NAME TYPE STATE ERRORS INTENT game-server-firewall compute.beta.firewall COMPLETED [] test-cluster container.v1.cluster COMPLETED [] make gcloud-auth-cluster make[1]: Entering directory `/home/markmandel/workspace/agones/src/agones.dev/agones/build' mkdir -p ~/.kube mkdir -p /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud docker run --rm -v /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v /home/markmandel/workspace/agones/src/agones.dev/agones:/go/src/agones.dev/agones agones-build:0229fec933 gcloud config set container/cluster test-cluster Updated property [container/cluster]. docker run --rm -v /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v /home/markmandel/workspace/agones/src/agones.dev/agones:/go/src/agones.dev/agones agones-build:0229fec933 gcloud config set compute/zone \ `grep zone: /home/markmandel/workspace/agones/src/agones.dev/agones/build//gke-test-cluster/deployment.yml | sed 's/zone: //'` Updated property [compute/zone]. docker run --rm -v /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v /home/markmandel/workspace/agones/src/agones.dev/agones:/go/src/agones.dev/agones agones-build:0229fec933 gcloud container clusters get-credentials test-cluster Fetching cluster endpoint and auth data. kubeconfig entry generated for test-cluster. docker run --rm -v /home/markmandel/workspace/agones/src/agones.dev/agones/build//.config/gcloud:/root/.config/gcloud -v ~/.kube:/root/.kube -v /home/markmandel/workspace/agones/src/agones.dev/agones:/go/src/agones.dev/agones agones-build:0229fec933 kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user $(gcloud config get-value account) /bin/sh: gcloud: command not found Error: flag needs an argument: --user

Examples:
# Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole
kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1

Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.
--clusterrole='': ClusterRole this ClusterRoleBinding should reference
--dry-run=false: If true, only print the object that would be sent, without sending it.
--generator='clusterrolebinding.rbac.authorization.k8s.io/v1alpha1': The name of the API generator to use.
--group=[]: Groups to bind to the role
--no-headers=false: When using the default or custom-column output format, don't print headers (default print headers).
--openapi-validation=true: If true, use openapi rather than swagger for validation.
-o, --output='': Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--schema-cache-dir='~/.kube/schema': If non-empty, load/store cached API schemas in this directory, default is '$HOME/.kube/schema'
--serviceaccount=[]: Service accounts to bind to the role, in the format :
-a, --show-all=false: When printing, show all resources (default hide terminated pods.)
--show-labels=false: When printing, show all labels as the last column (default hide labels column)
--sort-by='': If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--user=[]: Usernames to bind to the role
--validate=true: If true, use a schema to validate the input before sending it

Usage:
kubectl create clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]

Use "kubectl options" for a list of global command-line options (applies to all commands).

make[1]: [gcloud-auth-cluster] Error 1 (ignored)
make[1]: Leaving directory `/home/markmandel/workspace/agones/src/agones.dev/agones/build'

@markmandel
Copy link
Member

The other thing I'm running into (at least on minikube, I haven't test on gke yet), is that the grpc SDK can't connect sdk-sidecar process. All I see is this in the logs for the cpp gameserver:

root@markmandel:/go/src/agones.dev/agones# kubectl logs cpp-simple-wx2v2-bqvtt -c cpp-simple
C++ Game Server has started!
Getting the instance of the SDK!
Attempting to connect...

@dzlier-gcp
Copy link
Contributor Author

Is RBAC enabled in your cluster?

@dzlier-gcp
Copy link
Contributor Author

As for gRPC not being able to connect, can you tell which resource/verb pair is missing exactly?

build/Makefile Outdated
@@ -233,6 +233,7 @@ gcloud-auth-cluster: ensure-build-image
docker run --rm $(common_mounts) $(build_tag) gcloud config set compute/zone \
`grep zone: $(build_path)/gke-test-cluster/deployment.yml | sed 's/zone: //'`
docker run --rm $(common_mounts) $(build_tag) gcloud container clusters get-credentials $(CLUSTER_NAME)
-docker run --rm $(common_mounts) $(build_tag) kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user $$(gcloud config get-value account)
Copy link
Member

Choose a reason for hiding this comment

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

Worked out the bug. This should be:
-docker run --rm $(common_mounts) $(build_tag) bash -c 'kubectl create clusterrolebinding cluster-admin-binding --clusterrole cluster-admin --user $$(gcloud config get-value account)'

This pushes all the command down into the container, so the gcloud command doesn't get evaluated beforehand.

@markmandel
Copy link
Member

@dzlier-gcp yeah, I have RBAC enabled, I started my minikube cluster with:

$(MINIKUBE) start --kubernetes-version v1.8.0 --vm-driver $(MINIKUBE_DRIVER) \
		--extra-config=apiserver.Authorization.Mode=RBAC

as per https://kubernetes.io/docs/getting-started-guides/minikube/#examples

Testing on GKE next, see if it's just a minikube issue.

@markmandel
Copy link
Member

@dzlier-gcp works fine on GKE - so it's a minikube issue! Investigating.

markmandel added a commit that referenced this pull request Feb 13, 2018
@markmandel
Copy link
Member

Fixed the final minikube issues on commit af9ed94, feature/rbac-mark-fixes branch.

If you are happy, I can also merge them here and/or rebase against master, or you can cherry pick the change across and rebase. Up to you.

@markmandel markmandel merged commit 098f5a3 into master Feb 13, 2018
@markmandel markmandel deleted the feature/rbac branch February 13, 2018 18:07
@markmandel markmandel added this to the 0.1 milestone May 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants