{"id":13305714,"url":"https://github.com/anderslauri/open-iap","last_synced_at":"2025-03-10T13:32:22.236Z","repository":{"id":223112575,"uuid":"759332372","full_name":"anderslauri/open-iap","owner":"anderslauri","description":"Open Programmatic Identity Aware Proxy for Google Cloud","archived":false,"fork":false,"pushed_at":"2024-04-01T11:15:36.000Z","size":158,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-04-02T12:20:54.874Z","etag":null,"topics":["gke","google-service-account","google-workspace","iap","identity-aware-proxy","ingress","ingress-nginx","jwt","jwt-authentication"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anderslauri.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":"2024-02-18T09:47:46.000Z","updated_at":"2024-02-23T13:20:32.000Z","dependencies_parsed_at":"2024-04-01T11:51:12.076Z","dependency_job_id":null,"html_url":"https://github.com/anderslauri/open-iap","commit_stats":null,"previous_names":["anderslauri/k8s-gws-authn","anderslauri/eleutheria-gcp-iap"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anderslauri%2Fopen-iap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anderslauri%2Fopen-iap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anderslauri%2Fopen-iap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anderslauri%2Fopen-iap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anderslauri","download_url":"https://codeload.github.com/anderslauri/open-iap/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242859791,"owners_count":20196994,"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","google-service-account","google-workspace","iap","identity-aware-proxy","ingress","ingress-nginx","jwt","jwt-authentication"],"created_at":"2024-07-29T17:54:00.120Z","updated_at":"2025-03-10T13:32:21.967Z","avatar_url":"https://github.com/anderslauri.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Open Programmatic Identity Aware Proxy for Google Cloud\nOpen implementation of Programmatic Identity Aware Proxy for Google Cloud workload to workload authentication using Google Service Account.\nPerforms validity and signature verification of Google Service Account JWT - while also verifying subject of claim `email` has role bidning\n`roles/iap.httpsResourceAccess` inside project. Role `roles/iap.httpsResourceAccess` (as with Identity Aware Proxy) is required for authentication.\nConditional expressions are supported. A role binding can be restricted to only allow communication to a single specific `host` and `path`.\n\nThe following token types are supported for Google Service Account:\n\n- **ID-Token**\n- **Self-Signed JWTs**\n\nPlease reference [Google Cloud Token Types][Google Cloud Token Types] for more information. For **Self-Signed JWTs** please ensure to follow\n[specification as required by Google][Self-Signed JWTs].\n\n## Why?\n- Identity Aware Proxy for Google Cloud is only available in BeyondCorp Enterprise.\n- There is other solutions available on GitHub, however, none of are really suitable and made compatible with existing IAM on Google Cloud.\n\n## Authentication of Google Cloud Service Account\n1. Signature verification using `JWK`. Source of `JWK` is determined given type of JWT.\n2. `iat` and `exp` claim verification. Leeway for `JWT` is configurable. Default is 1 minute.\n3. `aud` claim must be equal to request url.\n4. Role `roles/iap.httpsResourceAccessor` is verified given subject of claim email. Role binding can be granted directly on project,\n   or indirectly, via membership in Google Workspace group.\n\n:exclamation: Steps `{1..3}` follow [JWT-verification as described by Google Cloud][JWT-Verification]. Step `4` is custom step following\nthe ideas of `Identity Aware Proxy`.\n\n:exclamation: After successful `{1..4}`. Value of claim `email` is cached. Key is hash, in `SHA256`, of `{JWT || Request URL}`. \n`ttl` for cache value is `exp - \u003cinterval of cleaning routine\u003e`. Once token is found in cache - only `exp` claim validity and step `4` is performed per each request.\n\n:exclamation: The code strives to retain a performance aware profile. Caching is used aggressivly on multiple layers to ensure an overall\nlow 90th percentile response time. To benefit from cache locality, use a ring hash for routing.\n\n## Role bindings\n:warning: All role bindings are consumed asynchronously given a defined time interval (see configuration). This may or\nmay not be acceptable - depends on your choice. Bindings are kept in memory for performance reasons. Default interval is `5min`.\n\n### Conditional expressions\n`request.path`, `request.host` and `request.time` are supported with conditional expressions with role `roles/iap.httpsResourceAccessor`. \nIf role binding has conditional expression, this conditional expression is compiled and evaluated in memory using `cel-go`. All conditional\nexpressions are only compiled once - after first compilation - the program (representing conditional expression) is cached for performance reasons.\n\n## How to run\n:exclamation: Use `Dockerfile` as example.\n\nConfiguration uses [pkl-lang][pkl-lang]. `pkl` must be available in `$PATH`. As well, `default_config.pkl` \nand `app_config.pkl` must be present in same directory as application executable when starting application.\n\n### Required Prerequisites\n* **Groups Reader** is required on Google Workspace. Reference [Google Workspace Administrator Roles][Google Workspace Administrator Roles].\n* **resourcemanager.projects.getIamPolicy** is required to list all bindings for role `roles/iap.httpsResourceAccess` \nfor Google Service Account inside project. Usage of custom role is recommended!\n* **Admin API** and **Cloud Resource Manager API** is required on project.\n\n## API \n\n### /auth (GET)\nAuthentication endpoint. Return code `200 OK` given successful authentication, else `401 Unauthorized`.\n\n#### Zero Trust with NetworkPolicy and nginx\nUse the following example (as inspiration), to enable secure, zero trust based communication of workload to workload communication to services on `GKE`.\n\n##### Configuration NetworkPolicy\nEnforce connectivity restrictions to service, traffic must only be permitted through `namespace` of `nginx`.\n\n````\napiVersion: networking.k8s.io/v1\nkind: NetworkPolicy\nmetadata:\n  name: my-service\nspec:\n  ingress:\n    - from:\n        - namespaceSelector:\n            matchExpressions:\n              - key: kubernetes.io/metadata.name\n                operator: In\n                values:\n                - nginx\n      ports:\n      - port: 8080\n        protocol: TCP\n  podSelector:\n    matchLabels:\n      app: my-service\n  policyTypes:\n  - Ingress\n`````\n\n##### Global nginx configuration\nDefine following configuration on `controller` of `nginx`. Ensuring, requests (all `ingress` registered with `controller`), only are permitted given valid authentication.\n\n```\nglobal-auth-snippet: |\n  proxy_set_header Proxy-Authorization $http_proxy_authorization;\nglobal-auth-url: http://\u003cservice name\u003e.\u003cnamespace\u003e:8080/auth\n```\n\n#### Required headers\n:warning: `X-Original-URL`, i.e. from `nginx` has assumed trust.\n\n1. `Authorization` or `Proxy-Authorization`.\n2. `X-Original-URL` is configured to be present. This can be changed using `HeaderMapping` in configuration.\n\n### /healthz (GET)\nKubernetes health endpoint for liveness and readiness. Return code `200 OK`.\n\n## Future changes\nIn scope for `open-iap`.\n\n1. Role `roles/iap.tunnelResourceAccessor` for `TUNNEL`-proxy.\n2. Role bindings on project level are only used. Folders and organization must be implemented as optional feature.\n3. Consume `IAM Role Audit Events`. Ensuring close to real time changes to policy bindings.\n\n[Google Workspace Groups API]: \u003chttps://developers.google.com/admin-sdk/directory/reference/rest/v1/groups\u003e \"Google Workspace Groups API\"\n[Google Workspace Administrator Roles]: \u003chttps://support.google.com/a/answer/2405986\u003e \"Google Workspace Administrator Roles\"\n[Google Cloud Token Types]: \u003chttps://cloud.google.com/docs/authentication/token-types\u003e \"Google Cloud Token Types\"\n[Programmatic Authentication]: \u003chttps://cloud.google.com/iap/docs/authentication-howto#authenticating_from_proxy-authorization_header\u003e \"Programmatic Authentication\"\n[JWT-verification]: \u003chttps://cloud.google.com/docs/authentication/token-types#id-aud\u003e \"JWT-verification\"\n[cel-go]: \u003chttps://github.com/google/cel-go\u003e \"cel-go\"\n[pkl-lang]: \u003chttps://pkl-lang.org/go/current/index.html\u003e \"pkl-lang\"\n[Self-Signed JWTs]: \u003chttps://cloud.google.com/iam/docs/create-short-lived-credentials-direct#create-jwt\u003e \"Self-Signed JWTs\"\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanderslauri%2Fopen-iap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanderslauri%2Fopen-iap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanderslauri%2Fopen-iap/lists"}