{"id":15222159,"url":"https://github.com/googlecloudplatform/gke-network-policy-demo","last_synced_at":"2025-10-20T01:30:44.943Z","repository":{"id":33266837,"uuid":"142069238","full_name":"GoogleCloudPlatform/gke-network-policy-demo","owner":"GoogleCloudPlatform","description":"This guide demonstrates how to improve the security of your Kubernetes Engine by applying fine-grained restrictions to network communication. You will provision a simple HTTP server and two client pods in a Kubernetes Engine cluster, then use a Network Policy restrict connections from client pods.","archived":false,"fork":false,"pushed_at":"2023-12-14T21:50:19.000Z","size":227,"stargazers_count":99,"open_issues_count":13,"forks_count":86,"subscribers_count":30,"default_branch":"master","last_synced_at":"2024-12-18T08:40:50.693Z","etag":null,"topics":["gke","gke-helmsman","kubernetes","kubernetes-engine","networking","security"],"latest_commit_sha":null,"homepage":"","language":"Shell","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-23T21:04:02.000Z","updated_at":"2024-06-02T07:24:40.000Z","dependencies_parsed_at":"2024-01-16T20:25:33.952Z","dependency_job_id":"150521cc-829a-4250-94ed-f33b88e7d002","html_url":"https://github.com/GoogleCloudPlatform/gke-network-policy-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-network-policy-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-network-policy-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-network-policy-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GoogleCloudPlatform%2Fgke-network-policy-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GoogleCloudPlatform","download_url":"https://codeload.github.com/GoogleCloudPlatform/gke-network-policy-demo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":237243005,"owners_count":19278060,"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","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","kubernetes","kubernetes-engine","networking","security"],"created_at":"2024-09-28T15:10:52.439Z","updated_at":"2025-10-20T01:30:44.414Z","avatar_url":"https://github.com/GoogleCloudPlatform.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# How to use a Network Policy in Kubernetes Engine\n\n## Table of Contents\n\n\u003c!-- TOC --\u003e\n\n  * [Introduction](#introduction)\n  * [Architecture](#architecture)\n  * [Initialize GCP Authorization](#initialize-gcp-authorization)\n  * [Deplyment steps](#deplyment-steps)\n     * [Setup this project](#setup-this-project)\n     * [Provisioning the Kubernetes Engine Cluster](#provisioning-the-kubernetes-engine-cluster)\n  * [Validation](#validation)\n  * [Installing the hello server](#installing-the-hello-server)\n  * [Confirming default access to the hello server](#confirming-default-access-to-the-hello-server)\n  * [Restricting access with a Network Policy](#restricting-access-with-a-network-policy)\n  * [Restricting namespaces with Network Policies](#restricting-namespaces-with-network-policies)\n  * [Validation](#validation-1)\n  * [Tear Down](#tear-down)\n  * [Troubleshooting](#troubleshooting)\n     * [The install script fails with a Permission denied when running Terraform](#the-install-script-fails-with-a-permission-denied-when-running-terraform)\n     * [Invalid fingerprint error during Terraform operations](#invalid-fingerprint-error-during-terraform-operations)\n  * [Relevant Material](#relevant-material)\n\n\u003c!-- TOC --\u003e\n\n## Introduction\n\nThis guide demonstrates how to improve the security of your Kubernetes Engine by applying fine-grained restrictions to network communication.\n\nThe Principle of Least Privilege is widely recognized as an important design consideration in enhancing the protection of critical systems from faults and malicious behavior (https://en.wikipedia.org/wiki/Principle_of_least_privilege). It suggests that every component must be able to access **only** the information and resources that are necessary for its legitimate purpose. This document demonstrates how the Principle of Least Privilege can be implemented within the Kubernetes Engine network layer.\n\nNetwork connections can be restricted at two tiers of your Kubernetes Engine infrastructure. The first, and coarser grained, mechanism is the application of Firewall Rules at the Network, Subnetwork, and Host levels. These rules are applied outside of the Kubernetes Engine at the VPC level.\n\nWhile Firewall Rules are a powerful security measure, Kubernetes enables us to define even finer grained rules via Network Policies. [Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/) are used to limit intra-cluster communication. Note that network policies do not apply to pods attached to the host's network namespace.\n\nThe steps below will provision a private Kubernetes Engine cluster and a bastion host with which to access it. A bastion host provides a single host that has access to the cluster, which, when combined with a private kubernetes network ensures that the cluster isn't exposed to malicious behavior from the internet at large. Bastions are particularly useful when you do not have VPN access to the cloud network.\n\nWithin the cluster, a simple HTTP server and two client pods will be provisioned. This tutorial will then demonstrate how to use a Network Policy and labeling to only allow connections from one of the client pods.\n\n## Architecture\n\nFor demonstration purposes, you will define a private Kubernetes cluster. Since the cluster is private, neither the API nor the worker nodes will be accessible from the internet. Instead, you will define a bastion host and use a firewall rule to enable access to it. The bastion's IP address is defined as an authorized network for the cluster, which grants it access to the API.\n\nWithin the cluster, provision three workloads:\n\n1. hello-server: this is a simple HTTP server with an internally-accessible endpoint\n1. hello-client-allowed: this is a single pod that repeatedly attempts to access hello-server. The pod is labeled such that the Network Policy will allow it to connect to hello-server.\n1. hello-client-blocked: this runs the same code as hello-client-allowed but the pod is labeled such that the Network Policy will __not__ allow it to connect to hello-server.\n\n![architecture](./img/architecture.png)\n\n\n## Initialize GCP Authorization\n\nWhen using Cloud Shell execute the following command in order to setup gcloud cli.\n\n```console\ngcloud init\n```\n\n## Deplyment steps\n\nThe following steps will allow a user to run the demo.\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\nFor simplicity, these parameters are to be specified in a file named `terraform.tfvars`, in the `terraform` directory. To ensure the appropriate APIs are enabled and to generate the `terraform/terraform.tfvars` file based on your gcloud defaults, run:\n\n```console\nmake setup-project\n```\n\nThis will enable the necessary Service APIs, and it will also generate a `terraform/terraform.tfvars` file with the following keys. The values themselves will match the output of `gcloud config list`:\n\n```console\ncat terraform/terraform.tfvars\n\nproject=\"YOUR_PROJECT\"\nregion=\"YOUR_REGION\"\nzone=\"YOUR_ZONE\"\n```\n\nIf you need to override any of the defaults, simply replace the desired value(s) to the right of the equals sign(s). Be sure your replacement values are still double-quoted.\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 tf-apply\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... (3m0s elapsed)\ngoogle_container_cluster.primary: Still creating... (3m10s elapsed)\ngoogle_container_cluster.primary: Still creating... (3m20s elapsed)\ngoogle_container_cluster.primary: Still creating... (3m30s elapsed)\ngoogle_container_cluster.primary: Creation complete after 3m34s (ID: gke-demo-cluster)\n\nApply complete! Resources: 5 added, 0 changed, 0 destroyed.\n```\n\nYou can also confirm the cluster was created successfully by ensuring that Network Policies are enabled for the new cluster. Verify that `networkPolicyConfig.disabled` is `false` and `networkPolicy.provider` is `CALICO`.\n\n```console\ngcloud container clusters describe gke-demo-cluster | grep  -A1 networkPolicy\n  networkPolicyConfig:\n    disabled: true\n--\nnetworkPolicy:\n  provider: CALICO\n\n```\n\nNow ssh into the bastion for the remaining steps.\n\n```console\ngcloud compute ssh gke-demo-bastion\n```\n\nThe newly-created cluster will now be available for the standard `kubectl` commands on the bastion.\n\n## Installing the hello server\n\nThe test application consists of one simple HTTP server, deployed as hello-server and two clients, one of which will be labeled as app=hello and the other app=not-hello.\n\nAll three services can be deployed by applying the hello-app manifests. On the bastion, run:\n\n```console\nkubectl apply -f ./manifests/hello-app/\n\ndeployment.apps/hello-client-allowed created\ndeployment.apps/hello-client-blocked created\nservice/hello-server created\ndeployment.apps/hello-server created\n```\n\nUse `kubectl get pods`` to verify all three pods have been successfully deployed.\nYou will see one running pod for each of *hello-client-allowed*, *hello-client-blocked*,\nand *hello-server* deployments.\n\n```console\nkubectl get pods\nNAME                                      READY     STATUS    RESTARTS   AGE\nhello-client-allowed-7d95fcd5d9-t8fsk   |  1/1      Running   0          14m\nhello-client-blocked-6497db465d-ckbn8   |  1/1      Running   0          14m\nhello-server-7df58f7fb5-nvcvd           |  1/1      Running   0          14m\n```\n\n## Confirming default access to the hello server\n\nOpen two new terminals and ssh into the bastion on both using the command:\n\n```console\ngcloud compute ssh gke-demo-bastion\n```\n\nTail the logs for the clients in each console:\n\nIn the first of the two newly created terminals, tail the \"allowed\" client:\n\n```console\nkubectl logs --tail 10 -f $(kubectl get pods -oname -l app=hello)\n```\n\nIn the second newly created terminal, tail the logs of the \"blocked\" client:\n\n```console\nkubectl logs --tail 10 -f $(kubectl get pods -oname -l app=not-hello)\n```\n\nYou will notice that both pods are successfully able to connect to the `hello-server` service. This is because you have not yet defined a Network Policy to restrict access. In each of these windows you should see successful responses from the server.\n\n```console\nHostname: hello-server-7df58f7fb5-nvcvd\nHello, world!\nVersion: 1.0.0\nHostname: hello-server-7df58f7fb5-nvcvd\nHello, world!\nVersion: 1.0.0\nHostname: hello-server-7df58f7fb5-nvcvd\n...\n```\n\n## Restricting access with a Network Policy\n\nIn this step you will block access to the `hello-server` pod from all pods that are not labeled with `app=hello`.\n\nThe policy definition you'll use is contained in `manifests/network-policy.yaml`\n\nApply the policy with the following command:\n\n```console\nkubectl apply -f ./manifests/network-policy.yaml\n\nnetworkpolicy.networking.k8s.io/hello-server-allow-from-hello-client created\n```\n\nYou'll now see that the output looks like this in the window tailing the \"blocked\" client:\n\n```console\nwget: download timed out\nwget: download timed out\nwget: download timed out\nwget: download timed out\nwget: download timed out\nwget: download timed out\nwget: download timed out\nwget: download timed out\nwget: download timed out\n...\n```\n\nIndicating that the network policy has now prevented communication to the `hello-server` from the unlabeled pod.\n\n## Restricting namespaces with Network Policies\n\nIn the previous example, you defined a network policy that restricts connections based on pod labels. It is often useful to instead label entire namespaces, particularly when teams or applications are granted their own namespaces.\n\nYou'll now modify the network policy to only allow traffic from a designated namespace, then you'll move the `hello-allowed` pod into that new namespace.\n\nFirst, delete the existing network policy and create the namespaced version\n\n```console\nkubectl delete -f ./manifests/network-policy.yaml\n\nnetworkpolicy.networking.k8s.io \"hello-server-allow-from-hello-client\" deleted\n```\n\n```console\nkubectl create -f ./manifests/network-policy-namespaced.yaml\n\nnetworkpolicy.networking.k8s.io/hello-server-allow-from-hello-client created\n```\n\nNow observe the logs of the `hello-allowed-client` pod in the default namespace. You will notice it is no longer able to connect to the `hello-server`.\n\nFinally, deploy a second copy of the hello-clients app into the new namespace.\n\n```console\nkubectl -n hello-apps apply -f ./manifests/hello-app/hello-client.yaml\n\ndeployment.apps/hello-client-allowed created\ndeployment.apps/hello-client-blocked created\n```\n\n## Validation\n\nCheck the logs for the two new `hello-app` clients and you will see that both clients are able to connect successfully. This is because, *as of Kubernetes 1.10.x NetworkPolicies do not support restricting access to pods within a given namespace*. You can whitelist by pod label, namespace label, or whitelist the union (ie OR) of both. But you cannot yet whitelist the intersection (ie AND) of pod labels and namespace labels.\n\nView the logs for the \"hello\"-labeled app in the app in the `hello-apps` namespace:\n\n```console\nkubectl logs --tail 10 -f -n hello-apps $(kubectl get pods -oname -l app=hello -n hello-apps)\n\nHostname: hello-server-6c6fd59cc9-7fvgp\nHello, world!\nVersion: 1.0.0\nHostname: hello-server-6c6fd59cc9-7fvgp\nHello, world!\nVersion: 1.0.0\nHostname: hello-server-6c6fd59cc9-7fvgp\nHello, world!\nVersion: 1.0.0\nHostname: hello-server-6c6fd59cc9-7fvgp\nHello, world!\nVersion: 1.0.0\nHostname: hello-server-6c6fd59cc9-7fvgp\n```\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...snip...\ngoogle_compute_subnetwork.cluster-subnet: Still destroying... (ID: us-east1/kube-net-subnet, 20s elapsed)\ngoogle_compute_subnetwork.cluster-subnet: Destruction complete after 25s\ngoogle_compute_network.gke-network: Destroying... (ID: kube-net)\ngoogle_compute_network.gke-network: Still destroying... (ID: kube-net, 10s elapsed)\ngoogle_compute_network.gke-network: Still destroying... (ID: kube-net, 20s elapsed)\ngoogle_compute_network.gke-network: Destruction complete after 26s\n\nDestroy complete! Resources: 5 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* [Terraform Google Provider](https://www.terraform.io/docs/providers/google/)\n* [Kubernetes Network Policies](https://kubernetes.io/docs/concepts/services-networking/network-policies/)\n* [Kubernetes Engine - Creating a Cluster Network Policy](https://cloud.google.com/kubernetes-engine/docs/how-to/network-policy)\n* [Kubernetes Engine - Network Policy Tutorial](https://cloud.google.com/kubernetes-engine/docs/tutorials/network-policy)\n* [Kubernetes Engine - Hardening your cluster's security](https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster)\n\n**This is not an officially supported Google product**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecloudplatform%2Fgke-network-policy-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgooglecloudplatform%2Fgke-network-policy-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgooglecloudplatform%2Fgke-network-policy-demo/lists"}