{"id":17604290,"url":"https://github.com/kubevirt-ui/kube-gateway","last_synced_at":"2025-04-30T10:09:57.452Z","repository":{"id":47448791,"uuid":"342052499","full_name":"kubevirt-ui/kube-gateway","owner":"kubevirt-ui","description":"Access k8s API using time limited access tokens.","archived":false,"fork":false,"pushed_at":"2024-05-30T08:35:34.000Z","size":21166,"stargazers_count":13,"open_issues_count":0,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-25T06:43:27.751Z","etag":null,"topics":["cluster","jwt","jwt-bearer-tokens","kubernetes","kubevirt","novnc","okd","openshift","openshift-origin"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/kubevirt-ui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2021-02-24T22:24:32.000Z","updated_at":"2024-05-30T08:35:06.000Z","dependencies_parsed_at":"2024-06-19T02:58:05.149Z","dependency_job_id":"8a6fbef0-361c-409b-9082-9353d4abbc7f","html_url":"https://github.com/kubevirt-ui/kube-gateway","commit_stats":null,"previous_names":["yaacov/oc-proxy","yaacov/oc-gate"],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubevirt-ui%2Fkube-gateway","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubevirt-ui%2Fkube-gateway/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubevirt-ui%2Fkube-gateway/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kubevirt-ui%2Fkube-gateway/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kubevirt-ui","download_url":"https://codeload.github.com/kubevirt-ui/kube-gateway/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242635331,"owners_count":20161437,"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":["cluster","jwt","jwt-bearer-tokens","kubernetes","kubevirt","novnc","okd","openshift","openshift-origin"],"created_at":"2024-10-22T14:08:35.955Z","updated_at":"2025-03-09T02:30:41.009Z","avatar_url":"https://github.com/kubevirt-ui.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n[![Go Report Card](https://goreportcard.com/badge/github.com/kubevirt-ui/kube-gateway)](https://goreportcard.com/report/github.com/kubevirt-ui/kube-gateway)\n[![Go Reference](https://pkg.go.dev/badge/github.com/kubevirt-ui/kube-gateway.svg)](https://pkg.go.dev/github.com/kubevirt-ui/kube-gateway)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n# kube-gateway\n\n![alt gopher network](https://raw.githubusercontent.com/kubevirt-ui/kube-gateway/main/docs/network-side.png)\n\nAccess the k8s API using time-limited access tokens. kube-gateway allows the usage of one-time access tokens to access k8s resources. Users\ncan use the default kube-gateway web application or create custom web applications that use the time-limited tokens to access the \nk8s API.\n\n## What can I do with it?\n\n- Create one-time links to access a k8s resource with a time-limited signed token (*).\n- Create custom web applications that can access the k8s API using time-limited signed tokens.\n\n(*) A signed token gives access to predefined k8s resources during a predefined time window.\n\n## Build the gateway server with a noVNC web application\n\n``` bash\n# Build the gateway locally:\ngo build -v ./cmd/...\n\n# Create and push the image into a container repository:\n# For example:\n# IMG=quay.io/kubevirt-ui/kube-gateway:v0.1.0 make image\nIMG=\u003cyour image repo\u003e make image\n\n# `make image` builds and push the image, it is equivalent to running:\n# podman build -t ${IMG} .\n# podman push ${IMG}\n```\n\n## Build a custom web application using the gateway\n\nAdd your application to the [/web/public](./web/public) directory and create an image.\n\n``` bash\n# For example, copy your static web application to the ./web/public/ directory.\ncp /dev/my-static-web-app/* ./web/public/\n\n# Create a container image and push it to your container repository.\nIMG=quay.io/myapps/custom-gateway:v0.0.1 make image\n```\n\n## Deploy service account, secrets, and route resources (when using OpenShift)\n\nThe [deploy](/deploy) directory contains example files to help create an example\nservice account with roles and secrets needed for running the gateway.\n\nRunning the gateway requires a service account that grants the gateway access to the k8s resources it\nwill proxy to the web application and secrets containing the public and private keys used to sign and \nverify the tokens.\n\n``` bash\n# Create a namespace for the gateway and service account using the deploy examples.\n# The example files will create a namespace called kube-gateway and a service account granting\n# reading privileges on the cluster. When deploying, users are encouraged to use minimal \n# privileges when creating a service account for the gateway proxy.\nkubectl create -f deploy/namespace.yaml\nkubectl create -f deploy/sa.yaml\n\n# Generate public and private keys (the gateway supports RSA signatures with SHA-256 hashes)\nopenssl genrsa -out tls.key\nopenssl req -new -x509 -sha256 -key tls.key -out tls.crt -days 3650 -subj \"/C=/ST=/L=/O=/OU=/CN=/emailAddress=\"\n\n# Create two secrets containing the private and public keys.\n# NOTE: The service account running the gateway does not require access to the private key,\n# but the public key must be accessible to the web application.\nkubectl create secret generic kube-gateway-jwt --from-file=tls.crt -n kube-gateway\nkubectl create secret generic kube-gateway-jwt-private --from-file=tls.key -n kube-gateway\n\n# Create a serving certificate for the gateway TLS server.\n# NOTE: There is no need to create this secret manually if you are using OpenShift, as it is \n#       created automatically in that case. \nkubectl create secret generic kube-gateway-secrets --from-file=tls.key --from-file=tls.crt -n kube-gateway\n\n# Deploy the gateway in the example namespace using the example service account.\nkubectl create -f deploy/kube-gateway.yaml\n```\n\n``` bash\n# NOTE: On OpenShift, you can deploy the example route, but make\n#       sure to edit the route to match your cluster's DNS.\noc create -f deploy/route.yaml\n```\n\n``` bash\n# Check deployment and secrets.\nkubectl get secrets -n kube-gateway\nkubectl get pods -n kube-gateway\nkubectl get svc -n kube-gateway\n\n# On minikube, expose the service using:\n# minikube service kube-gateway-svc -n kube-gateway\n```\n\n## Create a signed token\n\nObtain the k8s bearer token required to access the secret with the private key.\n\n``` bash\n# Obtain the token of the kube-gateway-sa service account (can read kube-gateway-jwt-private secret).\nkubectl get secrets -n kube-gateway -o json | jq '[.items[] | select(.metadata.name | contains(\"kube-gateway-sa\")) | select(.type | contains(\"service-account-token\")) | .data.token][0]' | python -m base64 -d \u003e token\n```\n\n``` bash\n# Create a token payload.\n# Available fields:\n# URLs - The list of allowed APIs, a `*` postfix indicates any suffix is allowed\n# duration - The duration for which the token will be valid (default is `1h`)\n# from - The time the token will start to be valid in RFC3339 format. For example: \"2016-11-01T20:44:39Z\" (default is now)\n# verbs - The list of allowed verbs. For example: [\"get\",\"post\"] (default is [\"get\"])\ndata='{\"URLs\":[\"/api/*\",\"/apis/*\"],\"duration\":\"30m\"}'\ntoken=$(cat token)\nproxyurl=https://192.168.39.134:30345 # Use the URL of the gateway proxy\n\n# Sign the token using the secret private key.\ncurl -sk -H 'Accept: application/json' -H \"Authorization: Bearer ${token}\" -H \"Content-Type: application/json\" --request POST --data \"${data}\" \"${proxyurl}/auth/jwt/request\" | jq .Token\n```\n\n## Create a signed link to access specific k8s resources\n\nOnce a token is signed it can be used to access the k8s API as long as it remains valid. Users can only access URLs specified in the token payload and only if the gateway service account can access them.\n\n![alt vnc demo](https://github.com/kubevirt-ui/kube-gateway/blob/main/docs/vnc-demo.gif)\n\nIn this example we will use the default noVNC web application.\n\n``` bash\n# The example noVNC application requires KubeVirt to be installed.\n# On minikube, install KubeVirt using minikube addons. On other platforms, install\n# KubeVirt in the manner recommended for that platform.\n# minikube addons enable kubevirt\n\n# Wait for KubeVirt to finish installing and then start the example virtual machine.\nkubectl create -f deploy/vm.yaml\n\n# Check that the virtual machine is running.\nkubectl get vms -n kube-gateway\n```\n\nNow that the virtual machine is running, we can create a signed link to the KubeVirt noVNC server.\n\n``` bash\n# Copy the service account bearer token into a local file.\nkubectl get secrets -n kube-gateway -o json | jq '[.items[] | select(.metadata.name | contains(\"kube-gateway-sa\")) | select(.type | contains(\"service-account-token\")) | .data.token][0]' | python -m base64 -d \u003e token\n\n# Create a path to the k8s resource.\nname=testvm\nnamespace=kube-gateway\npath=/apis/subresources.kubevirt.io/v1/namespaces/$namespace/virtualmachineinstances/$name/vnc\n\n# Create a token payload for accessing the API path for 1 hour, starting now.\ndata=\"{\\\"URLs\\\":[\\\"${path}\\\"],\\\"duration\\\":\\\"1h\\\"}\"\ntoken=$(cat token) # Use a k8s token that can access the private key for signing the JWT\n\n# On minikube get the url:\n# minikube service kube-gateway-svc -n kube-gateway\n# Important: the gateway is running with tls, make sure to use https:// \nproxyurl=https://kube-gateway.apps-crc.testing # Use the URL of the gateway proxy\n\n# Use the /auth/jwt/request endpoint to sign the token payload using the private key secret.\n# The service account bearer token used in this command must be able to access the secret holding the private key.\njwt=$(curl -sk -H 'Accept: application/json' -H \"Authorization: Bearer ${token}\" -H \"Content-Type: application/json\" --request POST --data \"${data}\" \"${proxyurl}/auth/jwt/request\" | jq .Token)\n\n# Open the link in a browser.\n# The link is signed using ${jwt} and will access the k8s API at ${path}.\nsigned_link=\"${proxyurl}/auth/jwt/set?token=${jwt}\u0026name=${name}\u0026namespace=${namespace}\"\n\ngoogle-chrome \"${signed_link}\"\n```\n\n## Proxy server endpoints\n\n| Endpoint | Requires | Description\n|---|----|---|\n| / | | web application static files |\n| /auth/jwt/set | | endpoint for setting session JWT cookie |\n| /login | ([/web/public/login](/web/public/login)) | helper page that sets the JWT token as a web browser cookie |\n| /auth/login | flag `-oauth-server-enable` | login path to start the OAuth2 authentication process |\n| /auth/callback | flag `-oauth-server-enable` | OAuth2 authentication callback endpoint |\n| /auth/jwt/request | flag `-jwt-request-enable` | endpoint for generating JWT access keys |\n\n## Supported JWT claims\n\n| Claim | Example | Description  | Default |\n|---|---|---|---|\n|URLs | [\"/api/v1/pods/*\"] | list of allowed APIs, a `*` postfix indicates any suffix is allowed |\n|duration | \"25m\" | the duration for which the token will be valid | \"1h\"\n|from | \"2016-11-01T20:44:39Z\" | the time at which the token will start to be valid in RFC3339 format |  now\n|verbs | [\"get\",\"post\"] | list of allowed verbs  | [\"get\"]\n\n(gopher network image - [egonelbre/gophers](https://github.com/egonelbre/gophers))\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkubevirt-ui%2Fkube-gateway","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkubevirt-ui%2Fkube-gateway","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkubevirt-ui%2Fkube-gateway/lists"}