{"id":15222222,"url":"https://github.com/googlecloudplatform/gke-rbac-demo","last_synced_at":"2025-09-16T18:46:31.672Z","repository":{"id":33566062,"uuid":"142068783","full_name":"GoogleCloudPlatform/gke-rbac-demo","owner":"GoogleCloudPlatform","description":"This project covers two use cases for RBAC within a Kubernetes Engine cluster. First, assigning different permissions to user personas. Second, granting limited API access to an application running within your cluster. Since RBAC's flexibility can occasionally result in complex rules, you will also perform common steps for troubleshooting RBAC as a part of the second scenario.","archived":false,"fork":false,"pushed_at":"2024-08-19T20:33:58.000Z","size":813,"stargazers_count":166,"open_issues_count":16,"forks_count":83,"subscribers_count":38,"default_branch":"master","last_synced_at":"2025-07-29T07:32:17.799Z","etag":null,"topics":["gke","gke-helmsman","google-cloud-platform","kubernetes","kubernetes-engine","rbac","security"],"latest_commit_sha":null,"homepage":"","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GoogleCloudPlatform.png","metadata":{"files":{"readme":"README-QWIKLABS.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-23T20:59:31.000Z","updated_at":"2025-06-19T13:45:58.000Z","dependencies_parsed_at":"2024-09-28T15:11:07.594Z","dependency_job_id":"2b87fa8e-5dc5-4da4-a2d0-c8bc8d6aa911","html_url":"https://github.com/GoogleCloudPlatform/gke-rbac-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/GoogleCloudPlatform/gke-rbac-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-rbac-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-rbac-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-rbac-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-rbac-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GoogleCloudPlatform","download_url":"https://codeload.github.com/GoogleCloudPlatform/gke-rbac-demo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-rbac-demo/sbom","scorecard":{"id":58119,"data":{"date":"2025-08-11","repo":{"name":"github.com/GoogleCloudPlatform/gke-rbac-demo","commit":"6e17274a28e03ed8af8a5e01fc09117e11c265de"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.5,"checks":[{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: containerImage not pinned by hash: images/pod-labeler/Dockerfile:15: pin your Docker image by updating python:2.7-stretch to python:2.7-stretch@sha256:548e680020444b0f6ddc4c7b0c24964d1af5f47cd2e2b3b44d742852b8b09cfc","Warn: pipCommand not pinned by hash: images/pod-labeler/Dockerfile:22","Warn: pipCommand not pinned by hash: images/pod-labeler/Dockerfile:28","Info:   0 out of   1 containerImage dependencies pinned","Info:   0 out of   2 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-15T01:09:38.217Z","repository_id":33566062,"created_at":"2025-08-15T01:09:38.217Z","updated_at":"2025-08-15T01:09:38.217Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275465710,"owners_count":25469884,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-16T02:00:10.229Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gke","gke-helmsman","google-cloud-platform","kubernetes","kubernetes-engine","rbac","security"],"created_at":"2024-09-28T15:11:05.483Z","updated_at":"2025-09-16T18:46:31.636Z","avatar_url":"https://github.com/GoogleCloudPlatform.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Using Role-Based Access Control in Kubernetes Engine\n\n## Table of Contents\n\n\u003c!-- TOC --\u003e\n\n* [Introduction](#introduction)\n* [Architecture](#architecture)\n* [Deployment](#deployment)\n  * [Authenticate gcloud](#authenticate-gcloud)\n  * [Configure gcloud settings](#configuring-gcloud-settings)\n  * [Setup this project](#setup-this-project)\n  * [Cluster Deployment](#cluster-deployment)\n  * [Provisioning the Kubernetes Engine Cluster](#provisioning-the-kubernetes-engine-cluster)\n* [Validation](#validation)\n* [Scenario 1: Assigning permissions by user persona](#scenario-1-assigning-permissions-by-user-persona)\n  * [IAM - Role](#iam---role)\n    * [IAM - User](#iam---user)\n  * [Description of the test environment:](#description-of-the-test-environment)\n  * [Create the namespaces with:](#create-the-namespaces-with)\n  * [Create the roles with:](#create-the-roles-with)\n  * [Create the role bindings with:](#create-the-role-bindings-with)\n  * [Create a test pod with:](#create-a-test-pod-with)\n  * [Inspect it:](#inspect-it)\n* [Scenario 2: Assigning API permissions to a cluster application](#scenario-2-assigning-api-permissions-to-a-cluster-application)\n  * [Deploying the sample application](#deploying-the-sample-application)\n  * [Diagnosing an RBAC misconfiguration](#diagnosing-an-rbac-misconfiguration)\n  * [Fixing the serviceAccountName](#fixing-the-serviceaccountname)\n  * [Diagnosing insufficient privileges](#diagnosing-insufficient-privileges)\n  * [Identifying the application's role and permissions](#identifying-the-applications-role-and-permissions)\n  * [Adding permissions to a role](#adding-permissions-to-a-role)\n  * [Verifying successful configuration](#verifying-successful-configuration)\n  * [Key takeaways](#key-takeaways)\n* [Tear down](#tear-down)\n* [Troubleshooting](#troubleshooting)\n  * [Invalid fingerprint error during terraform apply](#invalid-fingerprint-error-during-terraform-apply)\n* [Relevant Material](#relevant-material)\n\n\u003c!-- TOC --\u003e\n\n## Introduction\n\nThis tutorial covers the usage and debugging of [role-based access control (RBAC)](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) in a Kubernetes Engine cluster.\n\nWhile RBAC resource definitions are standard across all Kubernetes platforms. Their interaction with underlying authentication and authorization providers need to be understood when building on any cloud provider.\n\nRBAC is a powerful security mechanism that provides great flexibility in how you restrict operations within a cluster. This tutorial will cover two use cases for RBAC:\n\n1. Assigning different permissions to user personas, namely owners and auditors.\n1. Granting limited API access to an application running within your cluster.\n\nSince RBAC's flexibility can occasionally result in complex rules, common steps for troubleshooting RBAC are included as part of scenario 2.\n\n## Architecture\n\nThis tutorial focuses on the use of RBAC within a Kubernetes Engine cluster. It demonstrates how varying levels of cluster privilege can be granted to different user personas. In particular, you will provision two service accounts to represent user personas and three namespaces: dev, test, and prod. The \"owner\" persona will have read-write access to all three namespaces, while the \"auditor\" persona will have read-only access and be restricted to the dev namespace.\n\n![Architecture Diagram](./img/rbac-diagram.png)\n\n## Deployment\n\nThe steps below will walk you through using terraform to deploy a Kubernetes Engine cluster that you will then use for installing test users, applications and RBAC roles.\n\n### Authenticate gcloud\n\nPrior to running this demo, ensure you have authenticated your gcloud client by running the following command:\n\n```console\ngcloud auth application-default login\n```\n\n### Configure gcloud settings\n\nRun `gcloud config list` and make sure that `compute/zone`, `compute/region` and `core/project` are populated with values that work for you. You can set their values with the following commands:\n\n```console\n# Where the region is us-east1\ngcloud config set compute/region us-east1\n\nUpdated property [compute/region].\n```\n\n```console\n# Where the zone inside the region is us-east1-c\ngcloud config set compute/zone us-east1-c\n\nUpdated property [compute/zone].\n```\n\n```console\n# Where the project name is my-project-name\ngcloud config set project my-project-name\n\nUpdated property [core/project].\n```\n\n### Setup this project\n\nThis project requires the following Google Cloud Service APIs to be enabled:\n\n* `compute.googleapis.com`\n* `container.googleapis.com`\n* `cloudbuild.googleapis.com`\n\nIn addition, the terraform configuration takes three parameters to determine where the Kubernetes Engine cluster should be created:\n\n* `project`\n* `region`\n* `zone`\n\nThese parameters will be configured based on your gcloud default settings from the prior step.\n\n### Provisioning the Kubernetes Engine Cluster\n\nNext, apply the terraform configuration with:\n\n```console\n# From within the project root, use make to apply the terraform\nmake create\n```\n\nWhen prompted if you want to deploy the plan, review the generated plan and enter `yes` to deploy the environment.\n\n## Validation\n\nOnce complete, terraform will output a message indicating successful creation of the cluster.\n\n```console\n...snip...\ngoogle_container_cluster.primary: Still creating... (2m50s elapsed)\ngoogle_container_cluster.primary: Still creating... (3m0s elapsed)\ngoogle_container_cluster.primary: Still creating... (3m10s elapsed)\ngoogle_container_cluster.primary: Still creating... (3m20s elapsed)\ngoogle_container_cluster.primary: Creation complete after 3m24s (ID: rbac-demo-cluster)\n\nApply complete! Resources: 14 added, 0 changed, 0 destroyed.\n```\n\nYou can also confirm the cluster was created successfully by logging into the cloud console and ensuring that Legacy Authorization is disabled for the new cluster.\n\n![Cluster settings in console](./img/cluster_in_console_updated.png)\n\n## Scenario 1: Assigning permissions by user persona\n\n### IAM - Role\n\nA role named `kube-api-ro-xxxxxxxx` (where `xxxxxxxx` is a random string) has been created with the permissions below as part of the terraform configuration in `iam.tf`. These permissions are the minimum required for any user that requires access to the Kubernetes API.\n\n1. container.apiServices.get\n1. container.apiServices.list\n1. container.clusters.get\n1. container.clusters.getCredentials\n\n### Simulating users\n\nThree service accounts have been created to act as Test Users:\n\n* admin: has admin permissions over the cluster and all resources\n* owner: has read-write permissions over common cluster resources\n* auditor: has read-only permissions within the dev namespace only\n\n```console\ngcloud iam service-accounts list\n\nNAME                                    EMAIL\nGKE Tutorial Admin                      gke-tutorial-admin@myproject.iam.gserviceaccount.com\nGKE Tutorial Auditor                    gke-tutorial-auditor@myproject.iam.gserviceaccount.com\nGKE Tutorial Owner                      gke-tutorial-owner@myproject.iam.gserviceaccount.com\n```\n\nThree test hosts have been provisioned by the terraform script. Each node has `kubectl` and `gcloud` installed and configured to simulate a different user persona.\n\n* __gke-tutorial-admin__: kubectl and gcloud are authenticated as a cluster administrator.\n* __gke-tutorial-owner__: simulates the 'owner' account\n* __gke-tutorial-auditor__: simulates the 'auditor'account\n\n```console\ngcloud compute instances list\n\nNAME                                             ZONE           MACHINE_TYPE   PREEMPTIBLE  INTERNAL_IP  EXTERNAL_IP     STATUS\nrbac-demo-cluster-default-pool-a9cd3468-4vpc    us-central1-a  n1-standard-1                10.0.96.5                    RUNNING\nrbac-demo-cluster-default-pool-a9cd3468-b47f    us-central1-a  n1-standard-1                10.0.96.6                    RUNNING\nrbac-demo-cluster-default-pool-a9cd3468-rt5p    us-central1-a  n1-standard-1                10.0.96.7                    RUNNING\ngke-tutorial-auditor                            us-central1-a  f1-micro                     10.0.96.4    35.224.148.28    RUNNING\ngke-tutorial-admin                              us-central1-a  f1-micro                     10.0.96.3    35.226.237.142   RUNNING\ngke-tutorial-owner                              us-central1-a  f1-micro                     10.0.96.2    35.194.58.130    RUNNING\n```\n\n### Creating the RBAC rules\n\nCreate the the namespaces, Roles, and RoleBindings by logging into the admin instance and applying the `rbac.yaml` manifest:\n\nInput:\n\n```console\n# SSH to the admin\ngcloud compute ssh gke-tutorial-admin\n```\n\nCreate the namespaces, roles, and bindings\n\n```console\nkubectl apply -f ./manifests/rbac.yaml\n\nnamespace \"dev\" created\nnamespace \"prod\" created\nnamespace \"test\" created\nrole.rbac.authorization.k8s.io \"dev-ro\" created\nclusterrole.rbac.authorization.k8s.io \"all-rw\" created\nclusterrolebinding.rbac.authorization.k8s.io \"owner-binding\" created\nrolebinding.rbac.authorization.k8s.io \"auditor-binding\" created\n```\n\n### Managing resources as the owner\n\nIn a new terminal, ssh into the owner instance and create a simple deployment in each namespace:\n\n```console\n# SSH to the \"owner\" instance\ngcloud compute ssh gke-tutorial-owner\n```\n\nCreate a server in each namespace:\n\n```console\nkubectl create -n dev -f ./manifests/hello-server.yaml\n\nservice/hello-server created\ndeployment.apps/hello-server created\n```\n\n```console\nkubectl create -n prod -f ./manifests/hello-server.yaml\n\nservice/hello-server created\ndeployment.apps/hello-server created\n```\n\n```console\nkubectl create -n test -f ./manifests/hello-server.yaml\n\nservice/hello-server created\ndeployment.apps/hello-server created\n```\n\nAs the owner, you will also be able to view all pods:\n\n```console\n# On the \"owner\" instance\n\n# List all hello-server pods in all namespaces\nkubectl get pods -l app=hello-server --all-namespaces\n\nNAMESPACE   NAME                            READY     STATUS    RESTARTS   AGE\ndev         hello-server-6c6fd59cc9-h6zg9   1/1       Running   0          6m\nprod        hello-server-6c6fd59cc9-mw2zt   1/1       Running   0          44s\ntest        hello-server-6c6fd59cc9-sm6bs   1/1       Running   0          39s\n```\n\n### Viewing resources as the auditor\n\nIn a new terminal, ssh into the auditor instance and try to view all namespaces:\n\n```console\n# SSH to the \"auditor\" instance\ngcloud compute ssh gke-tutorial-auditor\n```\n\nAttempt to list all pods\n\n```console\n# On the \"auditor\" instance\n\n# List all hello-server pods in all namespaces\nkubectl get pods -l app=hello-server --all-namespaces\n\nError from server (Forbidden): pods is forbidden: User \"gke-tutorial-auditor@myproject.iam.gserviceaccount.com\" cannot list pods at the cluster scope: Required \"container.pods.list\" permission\n```\n\nThe error indicates you don't have sufficient permissions. The auditor is restricted to viewing only the resources in the dev namespace, so you'll need to specify the namespace when viewing resources.\n\nAttempt to view pods in the dev namespace\n\n```console\n# On the \"auditor\" instance\nkubectl get pods -l app=hello-server --namespace=dev\n\nNAME                            READY     STATUS    RESTARTS   AGE\nhello-server-6c6fd59cc9-h6zg9   1/1       Running   0          13m\n```\n\nAttempt to view pods in the test namespace\n\n```console\n# On the \"auditor\" instance\nkubectl get pods -l app=hello-server --namespace=test\n\nError from server (Forbidden): pods is forbidden: User \"gke-tutorial-auditor@myproject.iam.gserviceaccount.com\" cannot list pods in the namespace \"test\": Required \"container.pods.list\" permission.\n```\n\nAttempt to view pods in the prod namespace\n\n```console\n# On the \"auditor\" instance\nkubectl get pods -l app=hello-server --namespace=prod\n\nError from server (Forbidden): pods is forbidden: User \"gke-tutorial-auditor@myproject.iam.gserviceaccount.com\" cannot list pods in the namespace \"prod\": Required \"container.pods.list\" permission.\n```\n\nFinally, verify the that the auditor has read-only access by trying to create and delete a deployment in the dev namespace:\n\n```console\n# On the \"auditor\" instance\n\n# Attempt to create a deployment\nkubectl create -n dev -f manifests/hello-server.yaml\n\nError from server (Forbidden): error when creating \"manifests/hello-server.yaml\": services is forbidden: User \"gke-tutorial-auditor@myproject.iam.gserviceaccount.com\" cannot create services in the namespace \"dev\": Required \"container.services.create\" permission.\nError from server (Forbidden): error when creating \"manifests/hello-server.yaml\": deployments.extensions is forbidden: User \"gke-tutorial-auditor@myproject.iam.gserviceaccount.com\" cannot create deployments.extensions in the namespace \"dev\": Required \"container.deployments.create\" permission.\n```\n\n```console\n# On the \"auditor\" instance\n\n# Attempt to delete the deployment\nkubectl delete deployment -n dev -l app=hello-server\n\nError from server (Forbidden): deployments.extensions \"hello-server\" is forbidden: User \"gke-tutorial-auditor@myproject.iam.gserviceaccount.com\" cannot update deployments.extensions in the namespace \"dev\": Required \"container.deployments.update\" permission.\n```\n\n## Scenario 2: Assigning API permissions to a cluster application\n\nIn this scenario you'll go through the process of deploying an application that requires access to the Kubernetes API as well as configure RBAC rules while troubleshooting some common use cases.\n\n### Deploying the sample application\n\nThe sample application will run as a single pod that periodically retrieves all pods in the default namespace from the API server and then applies a timestamp label to each one.\n\nDeploy the pod-labeler application. This will also deploy a Role, ServiceAccount, and RoleBinding for the pod.\n\n```console\n# SSH to the admin instance\ngcloud compute ssh gke-tutorial-admin\n\n# Apply the pod-labeler configuration\nkubectl apply -f manifests/pod-labeler.yaml\n\nrole.rbac.authorization.k8s.io/pod-labeler created\nserviceaccount/pod-labeler created\nrolebinding.rbac.authorization.k8s.io/pod-labeler created\ndeployment.apps/pod-labeler created\n```\n\n### Diagnosing an RBAC misconfiguration\n\nNow check the status of the pod. Once the container has finished creating, you'll see it error out. Investigate the error by inspecting the pods' events and logs\n\n```console\n# On the admin instance\n\n# Check the pod status\nkubectl get pods -l app=pod-labeler\n\nNAME                           READY     STATUS    RESTARTS   AGE\npod-labeler-6d9757c488-tk6sp   0/1       Error     1          1m\n```\n\n```console\n# On the admin instance\n\n# View the pod event stream\nkubectl describe pod -l app=pod-labeler | tail -n 20\n\nEvents:\n  Type     Reason     Age                     From                                                       Message\n  ----     ------     ----                    ----                                                       -------\n  Normal   Scheduled  7m35s                   default-scheduler                                          Successfully assigned default/pod-labeler-5b4bd6cf9-w66jd to gke-rbac-demo-cluster-default-pool-3d348201-x0pk\n  Normal   Pulling    7m34s                   kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk  pulling image \"gcr.io/pso-examples/pod-labeler:0.1.5\"\n  Normal   Pulled     6m56s                   kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk  Successfully pulled image \"gcr.io/pso-examples/pod-labeler:0.1.5\"\n  Normal   Created    5m29s (x5 over 6m56s)   kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk  Created container\n  Normal   Pulled     5m29s (x4 over 6m54s)   kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk  Container image \"gcr.io/pso-examples/pod-labeler:0.1.5\" already present on machine\n  Normal   Started    5m28s (x5 over 6m56s)   kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk  Started container\n  Warning  BackOff    2m25s (x23 over 6m52s)  kubelet, gke-rbac-demo-cluster-default-pool-3d348201-x0pk  Back-off restarting failed container\n\n```\n\n```console\n# On the admin instance\n\n# Check the pod's logs\nkubectl logs -l app=pod-labeler\n\nAttempting to list pods\nTraceback (most recent call last):\n  File \"label_pods.py\", line 13, in \u003cmodule\u003e\n    ret = v1.list_namespaced_pod(\"default\",watch=False)\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py\", line 12310, in list_namespaced_pod\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py\", line 12413, in list_namespaced_pod_with_http_info\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py\", line 321, in call_api\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py\", line 155, in __call_api\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py\", line 342, in request\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/rest.py\", line 231, in GET\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/rest.py\", line 222, in request\nkubernetes.client.rest.ApiException: (403)\nReason: Forbidden\nHTTP response headers: HTTPHeaderDict({'Date': 'Fri, 25 May 2018 15:33:15 GMT', 'Audit-Id': 'ae2a0d7c-2ab0-4f1f-bd0f-24107d3c144e', 'Content-Length': '307', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff'})\nHTTP response body: {\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"pods is forbidden: User \\\"system:serviceaccount:default:default\\\" cannot list pods in the namespace \\\"default\\\": Unknown user \\\"system:serviceaccount:default:default\\\"\",\"reason\":\"Forbidden\",\"details\":{\"kind\":\"pods\"},\"code\":403}\n```\n\nBased on this error, you can see a permissions error when trying to list pods via the API. The next step is to confirm you are using the correct ServiceAccount:\n\n### Fixing the serviceAccountName\n\nBy inspecting the pod's configuration, you can see it is using the default ServiceAccount rather than the custom Service Account:\n\n```console\n# On the admin instance\n\nkubectl get pod -oyaml -l app=pod-labeler\n\n...\nrestartPolicy: Always\nschedulerName: default-scheduler\nsecurityContext: {}\nserviceAccount: default\n...\n```\n\nThe `pod-labeler-fix-1.yaml` file contains the fix in the deployment's template spec:\n\n```yaml\n      # Fix 1, set the serviceAccount so RBAC rules apply\n      serviceAccount: pod-labeler\n```\n\nApply the fix and view the resulting change:\n\n```console\n# On the admin instance\n\n# Apply the fix 1\nkubectl apply -f manifests/pod-labeler-fix-1.yaml\n\nrole.rbac.authorization.k8s.io/pod-labeler unchanged\nserviceaccount/pod-labeler unchanged\nrolebinding.rbac.authorization.k8s.io/pod-labeler unchanged\ndeployment.apps/pod-labeler configured\n```\n\n```console\n# On the admin instance\n\n# View the change in the deployment configuration\nkubectl get deployment pod-labeler -oyaml\n\n  ...\n  restartPolicy: Always\n  schedulerName: default-scheduler\n  securityContext: {}\n  serviceAccount: pod-labeler\n  ...\n\n```\n\n### Diagnosing insufficient privileges\n\nOnce again, check the status of your pod and you'll notice it is still erring out, but with a different message this time.\n\n```console\n# On the admin instance\n\n# Check the status of your pod\nkubectl get pods -l app=pod-labeler\n\nNAME                          READY     STATUS             RESTARTS   AGE\npod-labeler-c7b4fd44d-mr8qh   0/1       CrashLoopBackOff   3          1m\n\n```\n\n```console\n# On the admin instance\n\n# Check the pod's logs\nkubectl logs -l app=pod-labeler\n\nAttempting to list pods\nlabeling pod pod-labeler-c7b4fd44d-mr8qh\nTraceback (most recent call last):\n  File \"label_pods.py\", line 22, in \u003cmodule\u003e\n    api_response = v1.patch_namespaced_pod(name=i.metadata.name, namespace=\"default\", body=body)\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py\", line 15376, in patch_namespaced_pod\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/apis/core_v1_api.py\", line 15467, in patch_namespaced_pod_with_http_info\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py\", line 321, in call_api\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py\", line 155, in __call_api\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/api_client.py\", line 380, in request\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/rest.py\", line 286, in PATCH\n  File \"build/bdist.linux-x86_64/egg/kubernetes/client/rest.py\", line 222, in request\nkubernetes.client.rest.ApiException: (403)\nReason: Forbidden\nHTTP response headers: HTTPHeaderDict({'Date': 'Fri, 25 May 2018 16:01:40 GMT', 'Audit-Id': '461fa750-57c9-4fea-8717-f1778828417f', 'Content-Length': '385', 'Content-Type': 'application/json', 'X-Content-Type-Options': 'nosniff'})\nHTTP response body: {\"kind\":\"Status\",\"apiVersion\":\"v1\",\"metadata\":{},\"status\":\"Failure\",\"message\":\"pods \\\"pod-labeler-c7b4fd44d-mr8qh\\\" is forbidden: User \\\"system:serviceaccount:default:pod-labeler\\\" cannot patch pods in the namespace \\\"default\\\": Unknown user \\\"system:serviceaccount:default:pod-labeler\\\"\",\"reason\":\"Forbidden\",\"details\":{\"name\":\"pod-labeler-c7b4fd44d-mr8qh\",\"kind\":\"pods\"},\"code\":403}\n```\n\nSince this is failing on a PATCH operation, you can also see the error in stackdriver. This is useful if the application logs are not sufficiently verbose:\n\n```console\n\nOn Stackdriver Logging page, click on the 'Advance filter' option and filter by:\n\nprotoPayload.methodName=\"io.k8s.core.v1.pods.patch\"\n\n```\n\n![Stack driver logs](./img/stackdriver.png)\n\n### Identifying the application's role and permissions\n\nUse the ClusterRoleBinding to find the ServiceAccount's Role and permissions\n\n```yaml\n# On the admin instance\n\n# Inspect the rolebinding definition\nkubectl get rolebinding pod-labeler -oyaml\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: RoleBinding\nmetadata:\n  creationTimestamp: 2018-06-01T18:49:18Z\n  name: pod-labeler\n  namespace: default\n  resourceVersion: \"8309\"\n  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/pod-labeler\n  uid: 7d16fff7-65cc-11e8-a48a-42010a005a04\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: Role\n  name: pod-labeler\nsubjects:\n- kind: ServiceAccount\n  name: pod-labeler\n  namespace: default\n```\n\nThe RoleBinding shows you need to inspect the `pod-labeler` Role in the default namespace. Here you can see the role is only granted permission to list pods.\n\n```yaml\n# On the admin instance\n\n# Inspect the role definition\nkubectl get role pod-labeler -oyaml\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  annotations:\n    kubectl.kubernetes.io/last-applied-configuration: |\n      {\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"Role\",\"metadata\":{\"annotations\":{},\"name\":\"pod-labeler\",\"namespace\":\"default\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"list\",\"patch\"]}]}\n  creationTimestamp: 2018-06-21T20:34:11Z\n  name: pod-labeler\n  namespace: default\n  resourceVersion: \"1288\"\n  selfLink: /apis/rbac.authorization.k8s.io/v1/namespaces/default/roles/pod-labeler\n  uid: 748b40f4-7592-11e8-a757-42010a005a03\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  verbs:\n  - list\n```\n\nSince the application requires PATCH permissions, you can add it to the \"verbs\" list\nof the role.\n\nThe `pod-labeler-fix-2.yaml` file contains the fix in it's rules/verbs section:\n\n```yaml\nrules:\n- apiGroups: [\"\"] # \"\" refers to the core API group\n  resources: [\"pods\"]\n  verbs: [\"list\",\"patch\"] # Fix 2: adding permission to patch (update) pods\n```\n\nApply the fix and view the resulting configuration:\n\n```console\n# On the admin instance\n\n# Apply Fix 2\nkubectl apply -f manifests/pod-labeler-fix-2.yaml\n\nrole.rbac.authorization.k8s.io/pod-labeler configured\nserviceaccount/pod-labeler unchanged\nrolebinding.rbac.authorization.k8s.io/pod-labeler unchanged\ndeployment.apps/pod-labeler configured\n```\n\n```console\n# On the admin instance\n\n# View the resulting change\nkubectl get role pod-labeler -oyaml\n\napiVersion: rbac.authorization.k8s.io/v1\nkind: Role\nmetadata:\n  annotations:\n    kubectl.kubernetes.io/last-applied-configuration: |\n      {\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"name\":\"pod-labeler\",\"namespace\":\"\"},\"rules\":[{\"apiGroups\":[\"\"],\"resources\":[\"pods\"],\"verbs\":[\"list\"]}]}\n  creationTimestamp: 2018-05-25T15:52:24Z\n  name: pod-labeler\n  resourceVersion: \"62483\"\n  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/pod-labeler\n  uid: 9e2dc8c5-6033-11e8-a97b-42010a005a03\nrules:\n- apiGroups:\n  - \"\"\n  resources:\n  - pods\n  verbs:\n  - list\n  - patch\n```\n\nBecause the pod-labeler may be in a back-off loop, the quickest way to test our fix is to kill the existing pod and let a new one take it's place:\n\n```console\n# On the admin instance\n\n# Kill the existing pod and let the deployment controller replace it\nkubectl delete pod -l app=pod-labeler\n\npod \"pod-labeler-8845f6488-5fpt9\" deleted\n```\n\n### Verifying successful configuration\n\nFinally, verify the new pod-labeler is running and check that the \"updated\" label has been applied.\n\n```console\n# On the admin instance\n\n# List all pods and show their labels\nkubectl get pods --show-labels\n\nNAME                          READY     STATUS    RESTARTS   AGE       LABELS\npod-labeler-c7b4fd44d-8g8ws   1/1       Running   0          1m        pod-template-hash=736098008,run=pod-labeler,updated=1527264742.09\n```\n\n```console\n# View the pod's logs to verify there are no longer any errors\nkubectl logs -l app=pod-labeler\n\nAttempting to list pods\nlabeling pod pod-labeler-6d9757c488-dftcr\nlabeling pod pod-labeler-c7b4fd44d-8g8ws\nlabeling pod python-b89455c85-m284f\n```\n\n### Key take-aways\n\n* Container and API server logs will be your best source of clues for diagnosing RBAC issues.\n* Use RoleBindings or ClusterRoleBindings to determine which role is specifying the permissions for a pod.\n* API server logs can be found in stackdriver under the Kubernetes resource.\n* Not all API calls will be logged to stack driver. Frequent, or verbose payloads are omitted by the Kubernetes' audit policy used in Kubernetes Engine. The exact policy will vary by Kubernetes version, but can be found in the [open source codebase](https://github.com/kubernetes/kubernetes/blob/master/cluster/gce/gci/configure-helper.sh#L740)\n\n## Tear down\n\nLog out of the bastion host and run the following to destroy the environment:\n\n```console\nmake teardown\n```\n\n```console\n...snip...\ngoogle_service_account.auditor: Destruction complete after 0s\nmodule.network.google_compute_subnetwork.cluster-subnet: Still destroying... (ID: us-east1/kube-net-subnet, 10s elapsed)\nmodule.network.google_compute_subnetwork.cluster-subnet: Still destroying... (ID: us-east1/kube-net-subnet, 20s elapsed)\nmodule.network.google_compute_subnetwork.cluster-subnet: Destruction complete after 26s\nmodule.network.google_compute_network.gke-network: Destroying... (ID: kube-net)\nmodule.network.google_compute_network.gke-network: Still destroying... (ID: kube-net, 10s elapsed)\nmodule.network.google_compute_network.gke-network: Still destroying... (ID: kube-net, 20s elapsed)\nmodule.network.google_compute_network.gke-network: Destruction complete after 25s\n\nDestroy complete! Resources: 14 destroyed.\n```\n\n## Troubleshooting\n\n### The install script fails with a `Permission denied` when running Terraform\n\nThe credentials that Terraform is using do not provide the necessary permissions to create resources in the selected projects. Ensure that the account listed in `gcloud config list` has necessary permissions to create resources. If it does, regenerate the application default credentials using `gcloud auth application-default login`.\n\n### Invalid fingerprint error during Terraform operations\n\nTerraform occasionally complains about an invalid fingerprint, when updating certain resources. If you see the error below, simply re-run the command. ![terraform fingerprint error](./img/terraform_fingerprint_error.png)\n\n## Relevant Material\n\n* [Kubernetes Engine Role-Based Access Control](https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control)\n* [Kubernetes Engine IAM Integration](https://cloud.google.com/kubernetes-engine/docs/how-to/iam-integration)\n* [Kubernetes Service Account Authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#service-account-tokens)\n* [Terraform Documentation](https://www.terraform.io/docs/providers/google/index.html)\n\n**This is not an officially supported Google product**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecloudplatform%2Fgke-rbac-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgooglecloudplatform%2Fgke-rbac-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecloudplatform%2Fgke-rbac-demo/lists"}