├── .gitignore ├── cleaning-up.md ├── create-namespaces.md ├── README.md ├── using-existing-cluster-roles.md ├── create-cluster.md ├── create-cluster-roles.md ├── create-roles.md ├── calling-from-pod.md ├── create-service-accounts.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | .sw? 2 | .*.sw? 3 | -------------------------------------------------------------------------------- /cleaning-up.md: -------------------------------------------------------------------------------- 1 | # Cleanup all Resources 2 | 3 | ```sh 4 | gcloud iam service-accounts delete cluster-user-1 -q 5 | gcloud iam service-accounts delete cluster-user-2 -q 6 | gcloud container clusters delete permissions-test-cluster 7 | ``` 8 | 9 | -------------------------------------------------------------------------------- /create-namespaces.md: -------------------------------------------------------------------------------- 1 | # Create Namespaces 2 | 3 | Namespaces serve as a logical division of resources within a Kubernetes cluster. 4 | When combined with RBAC, it becomes possible to enforce the divisions. 5 | 6 | These two Kubernetes namespaces will be used for showing how to grant different 7 | access to different users in different parts of the cluster. 8 | 9 | ```sh 10 | a-kubectl create namespace ns-1 11 | a-kubectl create namespace ns-2 12 | ``` 13 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gke-rbac-walkthrough 2 | 3 | This is not an official Google product. 4 | 5 | A walk through of RBAC in Kubernetes 1.6 on a Google Container Engine (GKE) 6 | cluster. 7 | 8 | Prerequisites: 9 | 1. `gcloud` utility installed 10 | - It must be version 151+. Run `gcloud version | grep "Google Cloud SDK"` to 11 | confirm. 12 | 1. `kubectl` installed 13 | - It must be version 1.6+. Run `kubectl version` to confirm. 14 | 15 | ## Labs 16 | 17 | 1. [Create a cluster](create-cluster.md) 18 | 1. [Create GCP Service Accounts to use for authenticating](create-service-accounts.md) 19 | 1. [Create some namespaces](create-namespaces.md) 20 | 1. [Create roles and role bindings](create-roles.md) 21 | 1. [Create cluster roles and role bindings](create-cluster-roles.md) 22 | 1. [Using Existing Cluster Roles](using-existing-cluster-roles.md) 23 | 1. [Accessing the API from a Pod](calling-from-pod.md) 24 | 1. [Cleaning up](cleaning-up.md) 25 | -------------------------------------------------------------------------------- /using-existing-cluster-roles.md: -------------------------------------------------------------------------------- 1 | # Using Existing Cluster Roles 2 | 3 | To divide a cluster between multiple teams, there are [existing cluster 4 | roles](https://kubernetes.io/docs/admin/authorization/rbac/#user-facing-roles) 5 | that are pre-configured to help with that. These are the steps to take use those 6 | cluster roles to configure users with admin priviledges in their own namespaces, 7 | and viewing permissions in the other namespace. 8 | 9 | The pre-configured cluster role to grant admin priviledge to a namespace is the 10 | `admin` cluster role. 11 | 12 | ```sh 13 | a-kubectl get clusterroles 14 | ``` 15 | 16 | Make the users administrators in their own namespaces by binding the cluster 17 | role to the user in the namespace where they should be administrators. 18 | 19 | ```sh 20 | a-kubectl create rolebinding account1-admin \ 21 | --clusterrole=admin \ 22 | --user=$account1 \ 23 | --namespace=ns-1 24 | a-kubectl create rolebinding account2-admin \ 25 | --clusterrole=admin \ 26 | --user=$account2 \ 27 | --namespace=ns-2 28 | ``` 29 | 30 | To make the users viewers in the opposite namespace, bind the `viewer` cluster 31 | role in the namespace where they should be a viewer. 32 | 33 | ```sh 34 | a-kubectl create rolebinding account1-view \ 35 | --clusterrole=view \ 36 | --user=$account1 \ 37 | --namespace=ns-2 38 | a-kubectl create rolebinding account2-view \ 39 | --clusterrole=view \ 40 | --user=$account2 \ 41 | --namespace=ns-1 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /create-cluster.md: -------------------------------------------------------------------------------- 1 | # Create a Cluster 2 | 3 | NOTE: Commands for disabling legacy authorization are in the process of being 4 | rolled out and may not be available as you read this. Expect updates within a 5 | week. 6 | 7 | You need to have a Kubernetes 1.6 cluster with legacy authorization disabled. 8 | 9 | As a transitionary step so that new GKE clusters behave as much as possible as 10 | they did before, legacy authorization and RBAC will both be enabled by default 11 | in new 1.6 clusters. According to how Kubernetes [combines authorization 12 | modes](https://kubernetes.io/docs/admin/authorization/), if either authorization 13 | mode authorizes a requested action, then it will be permitted. In order for RBAC 14 | permissions to be fully enforced and not overridden by the legacy authorization 15 | mechanism, the legacy authorization should be disabled. 16 | 17 | ## Create a New Cluster 18 | 19 | ```sh 20 | gcloud beta container clusters create permissions-test-cluster \ 21 | --cluster-version=1.6.1 \ 22 | --no-enable-legacy-authorization 23 | ``` 24 | 25 | ## Use an Existing Cluster 26 | 27 | 1. Verify the version of the existing cluster. The client version and the server 28 | version must be at least 1.6. 29 | ```sh 30 | kubectl version 31 | ``` 32 | 33 | 2. Disable the legacy authorization mechanism. It is safe to re-run this command 34 | if the legacy authorization mechanism has already been disabled. 35 | ```sh 36 | gcloud beta container clusters update permissions-test-cluster \ 37 | --no-enable-legacy-authorization 38 | ``` 39 | 40 | -------------------------------------------------------------------------------- /create-cluster-roles.md: -------------------------------------------------------------------------------- 1 | # Creating Cluster Roles 2 | 3 | Additional permissions will be granted to *account1* and *account2* for specific 4 | namespaces using a common role. 5 | 6 | ## Service Account 1 Listing Deployments in Namespace 1 7 | 8 | 1. Try to list the pods in `ns-1` using GCP Service Account 1. 9 | ```sh 10 | 1-kubectl get deployments --namespace=ns-1 11 | ``` 12 | 2. Why not just create a role without specifying a namespace, so that it isn't 13 | in a namespace and can be used anywhere? 14 | ```sh 15 | a-kubectl create role deployment-reader \ 16 | --verb=get \ 17 | --verb=list \ 18 | --verb=watch \ 19 | --resource=deployments 20 | ``` 21 | Well, actually, if you don't specify a namespace, it just goes into the 22 | default namespace, so it's still in a namespace. The default namespace is 23 | just like all the other namespaces, except it's where things go by default. 24 | ```sh 25 | a-kubectl get roles --all-namespaces 26 | ``` 27 | 3. Create a cluster role that contains the necessary permissions: 28 | ```sh 29 | a-kubectl create clusterrole deployment-reader \ 30 | --verb=get \ 31 | --verb=list \ 32 | --verb=watch \ 33 | --resource=deployments 34 | ``` 35 | 4. Create a role binding to associate the role with GCP Service Account 1. 36 | ```sh 37 | a-kubectl create rolebinding account1-deployment-reader-binding \ 38 | --clusterrole=deployment-reader \ 39 | --user=$account1 \ 40 | --namespace=ns-1 41 | ``` 42 | 5. Try again. 43 | ```sh 44 | 1-kubectl get deployments --namespace=ns-1 45 | ``` 46 | 47 | ## Service Account 2 Listing Deployments in Namespace 2 48 | 49 | 1. Try to list the pods in `ns-2` using GCP Service Account 2. 50 | ```sh 51 | 2-kubectl get deployments --namespace=ns-2 52 | ``` 53 | 2. Re-use the cluster role that was created. 54 | ```sh 55 | a-kubectl create rolebinding account2-deployment-reader-binding \ 56 | --clusterrole=deployment-reader \ 57 | --user=$account2 \ 58 | --namespace=ns-2 59 | ``` 60 | 3. List the pods in `ns-2` using GCP Service Account 2. 61 | ```sh 62 | 2-kubectl get deployments --namespace=ns-2 63 | ``` 64 | -------------------------------------------------------------------------------- /create-roles.md: -------------------------------------------------------------------------------- 1 | # Creating Roles 2 | 3 | Additional permissions will be granted to *account1* and *account2* for specific 4 | namespaces. 5 | 6 | ## Service Account 1 Listing Pods in Namespace 1 7 | 8 | 1. Try to list the pods in `ns-1` using GCP Service Account 1. 9 | ```sh 10 | 1-kubectl get pods --namespace=ns-1 11 | ``` 12 | 2. Create a role that contains the necessary permissions. 13 | ```sh 14 | a-kubectl create role pod-reader \ 15 | --verb=get \ 16 | --verb=list \ 17 | --verb=watch \ 18 | --resource=pods \ 19 | --namespace=ns-1 20 | ``` 21 | 22 | Note: If you get an error at this point: 23 | 24 | ```sh 25 | Error from server (Forbidden): roles.rbac.authorization.k8s.io "pod-reader" is forbidden: attempt to grant extra privileges: 26 | ``` 27 | 28 | There is currently a known issue where IAM Service Accounts are not 29 | automatically granted cluster admin authorization. To correct the issue: 30 | 31 | ```sh 32 | a-kubectl create clusterrolebinding cluster-admin-binding \ 33 | --clusterrole=cluster-admin \ 34 | --user=$primary_account 35 | ``` 36 | 37 | 3. Create a role binding to associate the role with GCP Service Account 1. 38 | ```sh 39 | a-kubectl create rolebinding account1-pod-reader-binding \ 40 | --role=pod-reader \ 41 | --user=$account1 \ 42 | --namespace=ns-1 43 | ``` 44 | 4. Try again. 45 | ```sh 46 | 1-kubectl get pods --namespace=ns-1 47 | ``` 48 | 49 | ## Service Account 2 Listing Pods 50 | 51 | 1. Try to list the pods in `ns-2` using GCP Service Account 2. 52 | ```sh 53 | 2-kubectl get pods --namespace=ns-2 54 | ``` 55 | 2. Re-use the role that was created. This role binding is expected to fail 56 | because the role is in `ns-1` and can not be linked with a role binding in 57 | `ns-2`. However, it is worth noting how this role binding fails. The role 58 | binding will successfully create, with no errors, but the permissions will 59 | have no effect. 60 | ```sh 61 | a-kubectl create rolebinding account2-pod-reader-binding \ 62 | --role=pod-reader \ 63 | --user=$account2 \ 64 | --namespace=ns-2 65 | ``` 66 | 3. Try to list the pods in `ns-2` using GCP Service Account 2. 67 | ```sh 68 | 2-kubectl get pods --namespace=ns-2 69 | ``` 70 | View existing roles: 71 | ```sh 72 | a-kubectl get roles --all-namespaces 73 | ``` 74 | Note: There is not a lot of static checking around roles and role bindings. 75 | In fact, even this is possible: 76 | ```sh 77 | a-kubectl create rolebinding account2-fallacious-binding \ 78 | --role=fallacious-role \ 79 | --user=$account2 \ 80 | --namespace=ns-2 81 | ``` 82 | 4. Re-use the role that was created in the namespace where it was created: 83 | ```sh 84 | 2-kubectl get pods --namespace=ns-1 85 | ``` 86 | 87 | ```sh 88 | a-kubectl create rolebinding account2-pod-reader-binding \ 89 | --role=pod-reader \ 90 | --user=$account2 \ 91 | --namespace=ns-1 92 | ``` 93 | 5. Try again. 94 | ```sh 95 | 2-kubectl get pods --namespace=ns-1 96 | ``` 97 | 98 | -------------------------------------------------------------------------------- /calling-from-pod.md: -------------------------------------------------------------------------------- 1 | # Calling the Kubernetes API from a Pod 2 | 3 | When an application is running inside a pod, it might be useful for it to access 4 | the Kubernetes API. A pod has a service account, specified in the manifest file 5 | or it gets the default service account associated with the namespace. The 6 | permissions associated with the Kubernetes Service Account are the permissions 7 | that will be given to the applications running in the pod. 8 | 9 | The following steps will start a pod with an explicit, non-default, Kubernetes 10 | Service Account, set some permissions and explore the limits of those 11 | permissions from inside a container running inside the pod. 12 | 13 | ## Start a Pod 14 | 15 | ```sh 16 | a-kubectl create serviceaccount k-sa-1 --namespace=ns-1 17 | a-kubectl run nginx-1 \ 18 | --image=nginx:latest \ 19 | --namespace=ns-1 \ 20 | --overrides='{ 21 | "spec": { 22 | "template": { 23 | "spec": { 24 | "serviceAccountName": "k-sa-1" 25 | } 26 | } 27 | } 28 | }' 29 | ``` 30 | 31 | A `run` command creates a deployment, a replicaset, pods and containers. 32 | 33 | You should be able to confirm the success of your deployment: 34 | 35 | ```sh 36 | ➜ a-kubectl get deployments --namespace=ns-1 37 | NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 38 | nginx-1 1 1 1 1 15m 39 | ➜ a-kubectl get replicasets --namespace=ns-1 40 | NAME DESIRED CURRENT READY AGE 41 | nginx-1-1297132431 1 1 1 15m 42 | ➜ a-kubectl get pods --namespace=ns-1 43 | NAME READY STATUS RESTARTS AGE 44 | nginx-1-1297132431-14k2v 1/1 Running 0 15m 45 | ``` 46 | 47 | The pod will have an associated service account which will determine what kind 48 | of permissions it has. To verify the associated service account is the one 49 | request in the run command: 50 | 51 | ```sh 52 | ➜ a-kubectl get pods \ 53 | --namespace=ns-1 \ 54 | -o custom-columns=NAME:metadata.name,SERVICEACCOUNT:spec.serviceAccountName 55 | NAME SERVICEACCOUNT 56 | nginx-1-1297132431-14k2v k-sa-1 57 | ``` 58 | 59 | In order to test the kind of access the pod has, start a shell inside the 60 | running container. 61 | ```sh 62 | a-kubectl exec \ 63 | -it $(a-kubectl get pods \ 64 | --namespace=ns-1 \ 65 | -l run=nginx-1 \ 66 | -o custom-columns=:metadata.name | tail -1) \ 67 | --namespace=ns-1 bash 68 | ``` 69 | 70 | `curl` isn't available in this container by default, but it makes a useful tool 71 | for directly exercising the API, so install it. 72 | 73 | ```sh 74 | apt-get update && apt-get install -y curl 75 | curl -ik https://kubernetes.default.svc.cluster.local/version 76 | ``` 77 | 78 | Note the fully qualified name for the Kubernetes API server endpoint. From 79 | inside a pod running in the default namespace, only `https://kubernetes/` is 80 | required because the API server is running in the default namespace. When trying 81 | to access the API server from a different namespace, the short DNS names from a 82 | different namespace will not resolve, and so the FQDN is necessary. 83 | 84 | Now, to do something more interesting, let's list the pods running in our 85 | namespace: 86 | 87 | ```sh 88 | curl -ik \ 89 | https://kubernetes.default.svc.cluster.local/api/v1/namespaces/ns-1/pods 90 | ``` 91 | 92 | However, listing pods in a namespace requires permissions, so that curl command 93 | should have resulted in an error message, and the error message should have 94 | indicated the `system:anonymous` user was used. So, why aren't requests from 95 | this pod coming from the `k-sa-1` user, which is the service account assigned to 96 | this pod? 97 | 98 | Every container in a cluster is populated with a token that can be used for 99 | authenticating to the API server. 100 | 101 | ```sh 102 | cat /var/run/secrets/kubernetes.io/serviceaccount/token 103 | ``` 104 | 105 | When requests are made including this token in the `Authorization` header, 106 | Kubernetes will identify the request as coming from the service account 107 | associated with the pod. 108 | 109 | ```sh 110 | curl -ik \ 111 | -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ 112 | https://kubernetes.default.svc.cluster.local/api/v1/namespaces/ns-1/pods 113 | ``` 114 | 115 | That curl command should have resulted in an error message as well, but for a 116 | different reason. Now that the correct user is being used, the problem is that 117 | service account doesn't have any permissions to list pods using the API server. 118 | 119 | Outside of the container shell, run: 120 | 121 | ```sh 122 | a-kubectl create role pod-lister \ 123 | --verb=list \ 124 | --resource=pods \ 125 | --namespace=ns-1 126 | a-kubectl create rolebinding pod-lister-binding \ 127 | --role=pod-lister \ 128 | --serviceaccount=ns-1:k-sa-1 \ 129 | --namespace=ns-1 130 | ``` 131 | 132 | Now, back inside the pod, try again: 133 | 134 | ```sh 135 | curl -ik \ 136 | -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ 137 | https://kubernetes.default.svc.cluster.local/api/v1/namespaces/ns-1/pods 138 | ``` 139 | 140 | Now, something that requires more permissions, listing the pods running in 141 | the default namespace: 142 | 143 | ```sh 144 | curl -ik \ 145 | -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \ 146 | https://kubernetes.default.svc.cluster.local/api/v1/namespaces/default/pods 147 | ``` 148 | 149 | Which fails because we did not grant any pod listing permissions on the default 150 | namespace. 151 | -------------------------------------------------------------------------------- /create-service-accounts.md: -------------------------------------------------------------------------------- 1 | # Create Service Accounts 2 | 3 | NOTE: You will need to enable the IAM API for some of these commands to work. 4 | 5 | In order to demonstrate how permissions work, 3 separate users will be used. 6 | Some special steps will be taken to make all three different users work on the 7 | same logged in account. An alias will be created for each one so that it is easy 8 | to see who is taking the action. 9 | 10 | 1. Admin - this user has full access to all namespaces in the cluster. 11 | 2. Account 1 - this user starts with no access and will be granted increasing 12 | levels of access to namespace 1. 13 | 3. Account 2 - this user starts with no access and will be granted increasing 14 | levels of access to namespace 2, possibly with some minor access to namespace 15 | 1. 16 | 17 | There are different ways to make authenticated entities, or subjects, work with 18 | the cluster. In this case, GCP Service Accounts (different from Kubernetes 19 | Service Accounts) will be used for Account 1 and Account 2. 20 | 21 | If at some point in these instructions `gcloud` commands stop responding due to 22 | permissions, you can renew your gcloud authentication: 23 | 24 | ```sh 25 | gcloud auth list 26 | gcloud config set account $primary_account 27 | ``` 28 | 29 | If you have any problem with `kubectl` commands not connecting to the cluster 30 | correctly, you can refresh `kubectl` credentials for your clusters: 31 | 32 | ```sh 33 | gcloud container clusters get-credentials permissions-test-cluster 34 | ``` 35 | 36 | ## Create Admin Alias 37 | 38 | Create the `a-kubectl` alias, an alias to `kubectl` that uses the token of the 39 | GCP project master account to authenticate. 40 | 41 | ```sh 42 | export primary_account="" 43 | alias a-kubectl='kubectl --token="$(gcloud auth print-access-token --account=$primary_account)"' 44 | ``` 45 | 46 | ## Creating First Service Account 47 | 48 | Create the `1-kubectl` alias, an alias to `kubectl` that uses a token associated 49 | with the new `cluster-user-1` GCP Service Account to authenticate. 50 | 51 | 1. Create a GCP service account. 52 | ```sh 53 | gcloud iam service-accounts create cluster-user-1 --display-name=cluster-user-1 54 | ``` 55 | 2. Capture the full service account name. 56 | ```sh 57 | account1=$(gcloud iam service-accounts list --format='value(email)' --filter='displayName:cluster-user-1') 58 | ``` 59 | 3. Create a key for the GCP service account. 60 | ```sh 61 | gcloud iam service-accounts keys create --iam-account $account1 cluster-user-1.json 62 | ``` 63 | 4. Use the GCP service account key to activate the service account. 64 | ```sh 65 | gcloud auth activate-service-account $account1 --key-file=cluster-user-1.json 66 | ``` 67 | 5. Create an alias to make it easy to use `kubectl` authenticating as the new 68 | service account. 69 | ```sh 70 | alias 1-kubectl='kubectl --token="$(gcloud auth print-access-token --account=$account1)"' 71 | ``` 72 | 6. Reset the active account to be ready for the next steps. 73 | ```sh 74 | gcloud config set account $primary_account 75 | ``` 76 | 77 | ## Creating Second Service Account 78 | 79 | Create the `2-kubectl` alias, an alias to `kubectl` that uses a token associated 80 | with the new `cluster-user-2` GCP Service Account to authenticate. 81 | 82 | This is just a repetition of the same steps for the second service account. 83 | 84 | ```sh 85 | gcloud iam service-accounts create cluster-user-2 --display-name=cluster-user-2 86 | account2=$(gcloud iam service-accounts list --format='value(email)' --filter='displayName:cluster-user-2') 87 | gcloud iam service-accounts keys create --iam-account $account2 cluster-user-2.json 88 | gcloud auth activate-service-account $account2 --key-file=cluster-user-2.json 89 | alias 2-kubectl='kubectl --token="$(gcloud auth print-access-token --account=$account2)"' 90 | gcloud config set account $primary_account 91 | ``` 92 | 93 | ## Enable GCP IAM Cluster Admin Roles 94 | 95 | In order for these new GCP Service Accounts to be able to do anything on 96 | clusters, they must have GCP IAM container engine permissions. 97 | 98 | 1. Navigate to https://console.cloud.google.com 99 | 2. Login 100 | 3. Select the GCP project that contains your GKE cluster from the drop down list 101 | on the top. 102 | 4. Expand the left menu and select `IAM & Admin` and the `IAM`. 103 | 5. Click `Add` 104 | 6. Enter the full email address of the user account that you are using as the 105 | admin user. 106 | 7. Select `Container`, then `Container Engine Admin` from the `Role` menu. 107 | 8. Add a second role by selecting `Container`, then `Container Engine Cluster 108 | Admin` from the `Role` menu. 109 | 9. Then click `Add` to add the new IAM roles to your user. 110 | 111 | ## Disable Configured Authentication 112 | 113 | The `~/.kube/config` file contains configuration about clusters your `kubectl` 114 | knows about. The aliases configured above use the `--token` parameter to 115 | authenticate cluster connections using a token associated with the correct 116 | service account. However, if there is a valid `auth-provider` section in the 117 | `~/.kube/config` for your cluster, it will override the `--token` parameter and 118 | all requests will be authenticated using the settings `~/.kube/config`. 119 | 120 | So, in this, edit the `~/.kube/config` file and comment out the `auth-provider` 121 | section associated with your test cluster. It should look something like this: 122 | 123 | ```yaml 124 | - name: gke_username-gke-dev_us-central1-d_permissions-test-cluster 125 | user: 126 | #auth-provider: 127 | # config: 128 | # access-token: ya29.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 129 | # expiry: 2017-01-01T13:23:15.856385727-07:00 130 | # name: gcp 131 | ``` 132 | 133 | ## Confirm Outcomes 134 | 135 | When the above configuration steps are complete, the admin alias should be able 136 | to list nodes, the other two aliases should not be able to do anything. 137 | 138 | ```sh 139 | ➜ a-kubectl get nodes 140 | NAME STATUS AGE VERSION 141 | gke-permissions-test-clu-default-pool-08b7c523-2lpt Ready 1h v1.6.1 142 | gke-permissions-test-clu-default-pool-08b7c523-tj2l Ready 1h v1.6.1 143 | gke-permissions-test-clu-default-pool-08b7c523-v2z9 Ready 1h v1.6.1 144 | ``` 145 | 146 | Observe in the error message that `cluster-user-1` is being refused permission. 147 | 148 | ```sh 149 | ➜ 1-kubectl get nodes 150 | Error from server (Forbidden): User "cluster-user-1@username-gke-dev.iam.gserviceaccount.com" cannot list nodes at the cluster scope.: "Required \"container.nodes.list\" permission." (get nodes) 151 | ``` 152 | 153 | Observe in the error message that `cluster-user-2` is being refused permission. 154 | 155 | ```sh 156 | ➜ 2-kubectl get nodes 157 | Error from server (Forbidden): User "cluster-user-2@username-gke-dev.iam.gserviceaccount.com" cannot list nodes at the cluster scope.: "Required \"container.nodes.list\" permission." (get nodes) 158 | ``` 159 | 160 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [2017] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------