diff --git a/content/docs/capabilities/non-http/examples/rdp.mdx b/content/docs/capabilities/non-http/examples/rdp.mdx index dc07408e3..3855acb44 100644 --- a/content/docs/capabilities/non-http/examples/rdp.mdx +++ b/content/docs/capabilities/non-http/examples/rdp.mdx @@ -64,12 +64,10 @@ Some clients, like Remmina, support running commands before and after connection -1. Save the script above to your home folder (`~/`), and make it executable: +1. Save the script above to your home folder as `~/pomerium-tunnel.sh`, then make it executable: ```bash - cd ~/ - wget https://github.com/pomerium/pomerium/blob/main/examples/tcp/pomerium-tunnel.sh - chmod +x pomerium-tunnel.sh + chmod +x ~/pomerium-tunnel.sh ``` 1. Update your client profile to execute the script before and after the connection: diff --git a/content/docs/guides/cloud-run.mdx b/content/docs/guides/cloud-run.mdx index f6ed39656..727a2eb37 100644 --- a/content/docs/guides/cloud-run.mdx +++ b/content/docs/guides/cloud-run.mdx @@ -22,8 +22,6 @@ See [this GitHub issue](https://github.com/pomerium/pomerium/issues/4091) for mo ::: -This recipe's sources can be found [on github](https://github.com/pomerium/pomerium/tree/main/examples/cloudrun) - ## Background Services on [Cloud Run](https://cloud.google.com/run) and other Google Cloud serverless products can be restricted to only permit access with a properly signed [bearer token](https://cloud.google.com/run/docs/authenticating/service-to-service). This allows requests from other services running in GCP or elsewhere to be securely authorized despite the endpoints being public. diff --git a/content/docs/reference/routes/tls.mdx b/content/docs/reference/routes/tls.mdx index 244ee2167..26f3deadd 100644 --- a/content/docs/reference/routes/tls.mdx +++ b/content/docs/reference/routes/tls.mdx @@ -30,7 +30,7 @@ This reference covers all of Pomerium's TLS route settings: If specified, Pomerium will present this client certificate to upstream services when requested to enforce [mutual authentication](https://en.wikipedia.org/wiki/Mutual_authentication) (mTLS). -For more details, see our [mTLS example repository](https://github.com/pomerium/pomerium/tree/main/examples/mutual-tls) and the [Upstream mTLS With Pomerium](/docs/internals/certificates-and-tls) guide. +For more details, see our [mTLS example](https://github.com/pomerium/documentation/tree/main/content/examples/mutual-tls) and the [Upstream mTLS With Pomerium](/docs/internals/certificates-and-tls) guide. ### How to configure \{#how-to-configure-tls-client-certificate} diff --git a/content/examples/cloudrun/deploy.sh.md b/content/examples/cloudrun/deploy.sh.md index 0a9b193d7..407931100 100644 --- a/content/examples/cloudrun/deploy.sh.md +++ b/content/examples/cloudrun/deploy.sh.md @@ -4,7 +4,9 @@ ```bash title="deploy.sh" #!/bin/bash -# Install gcloud beta +# domain-mappings on fully-managed Cloud Run is still under `gcloud beta` +# (the GA `gcloud run domain-mappings` is Cloud Run for Anthos only and +# rejects --region as of gcloud SDK 555+). gcloud components install beta # Capture current project number diff --git a/content/examples/cloudrun/policy.template.yaml.md b/content/examples/cloudrun/policy.template.yaml.md index 4e516eca1..ea6679a9e 100644 --- a/content/examples/cloudrun/policy.template.yaml.md +++ b/content/examples/cloudrun/policy.template.yaml.md @@ -1,12 +1,18 @@ ```yaml title="policy.template.yaml" - from: https://hello.cloudrun.pomerium.io to: ${HELLO_URL} - allowed_domains: - - gmail.com enable_google_cloud_serverless_authentication: true + policy: + - allow: + or: + - domain: + is: gmail.com - from: https://verify.cloudrun.pomerium.io to: https://verify.pomerium.com pass_identity_headers: true - allowed_domains: - - gmail.com + policy: + - allow: + or: + - domain: + is: gmail.com ``` diff --git a/content/examples/config/config.docker.yaml.md b/content/examples/config/config.docker.yaml.md deleted file mode 100644 index c59d578f7..000000000 --- a/content/examples/config/config.docker.yaml.md +++ /dev/null @@ -1,27 +0,0 @@ -```yaml -# See detailed configuration settings: https://www.pomerium.com/docs/reference/ - -##################################################################### -# If self-hosting, use the localhost authenticate service URL below # -# and remove the hosted URL. # -##################################################################### -# authenticate_service_url: https://authenticate.localhost.pomerium.io - -authenticate_service_url: https://authenticate.pomerium.app - -#################################################################################### -# If self-hosting, you must configure an identity provider. # -# See identity provider settings: https://www.pomerium.com/docs/integrations/# -#################################################################################### - -# https://pomerium.com/reference/#routes -routes: - - from: https://verify.localhost.pomerium.io - to: http://verify:8000 - policy: - - allow: - or: - - email: - is: user@example.com - pass_identity_headers: true -``` diff --git a/content/examples/config/config.example.env b/content/examples/config/config.example.env deleted file mode 100644 index 26462c5e5..000000000 --- a/content/examples/config/config.example.env +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/bash -# Main configuration flags : https://www.pomerium.com/docs/reference/ - -# Main configuration flags -# export ADDRESS=":8443" # optional, default is 443 -# export SERVICE="all" # optional, default is all -# export LOG_LEVEL="info" # optional, default is debug - -export AUTHENTICATE_SERVICE_URL=https://authenticate.corp.beyondperimeter.com -# AUTHORIZE_SERVICE_URL service url will default to localhost in all-in-one mode, -# otherwise it should be set to a "behind-the-ingress" routable url -# export AUTHORIZE_SERVICE_URL=https://pomerium-authorize-service.default.svc.cluster.local -# DATABROKER_SERVICE_URL defaults to http://localhost:5443 in all-in-one mode. -# Set it only when the databroker runs on another host/port (split/remote Core). -# export DATABROKER_SERVICE_URL=https://pomerium-databroker-service.default.svc.cluster.local - -# Certificates can be loaded as files or base64 encoded bytes. -# See : https://www.pomerium.com/docs/reference/certificates -export AUTOCERT=TRUE # Use Let's Encrypt to fetch certs. Port 80/443 must be internet accessible. -# export AUTOCERT_DIR="./certs" # The path where you want to place your certificates -# export CERTIFICATE_FILE="xxxx" # optional -# export CERTIFICATE_KEY_FILE="xxx" # optional -# export CERTIFICATE="xxx" # base64 encoded cert, eg. `base64 -i cert.pem` -# export CERTIFICATE_KEY="xxx" # base64 encoded key, eg. `base64 -i private-key.pem` - -# Generate 256 bit random keys e.g. `head -c32 /dev/urandom | base64` -export SHARED_SECRET="$(head -c32 /dev/urandom | base64)" -export COOKIE_SECRET="$(head -c32 /dev/urandom | base64)" -# If set, a JWT based signature is appended to each request header `x-pomerium-jwt-assertion` -# export SIGNING_KEY="Replace with base64'd private key from ./scripts/self-signed-sign-key.sh" - -# Identity Provider Settings - -# Auth0 -# export IDP_PROVIDER="auth0" -# export IDP_PROVIDER_URL="https://REPLACE_ME.us.auth0.com" -# export IDP_CLIENT_ID="REPLACE_ME" # from the application the users login to -# export IDP_CLIENT_SECRET="REPLACE_ME" # from the application the users login to - -# Azure -# export IDP_PROVIDER="azure" -# export IDP_PROVIDER_URL="https://login.microsoftonline.com/REPLACE_ME/v2.0" -# export IDP_CLIENT_ID="REPLACE_ME -# export IDP_CLIENT_SECRET="REPLACE_ME" - -## GOOGLE -export IDP_PROVIDER="google" - -# OKTA -# export IDP_PROVIDER="okta" -# export IDP_CLIENT_ID="REPLACE_ME" -# export IDP_CLIENT_SECRET="REPLACE_ME" -# export IDP_PROVIDER_URL="https://REPLACE_ME.oktapreview.com/oauth2/default" - -# OneLogin -# export IDP_PROVIDER="onelogin" -# export IDP_CLIENT_ID="REPLACE_ME" -# export IDP_CLIENT_SECRET="REPLACE_ME" -# export IDP_PROVIDER_URL="https://openid-connect.onelogin.com/oidc" #optional, defaults to `https://openid-connect.onelogin.com/oidc` - -# Proxied routes and per-route policies are defined in a policy provided either -# directly as a base64 encoded yaml/json file, or as the policy key in the configuration -# file -export POLICY="$(base64 ./docs/configuration/examples/config/policy.example.yaml)" diff --git a/content/examples/config/config.example.yaml b/content/examples/config/config.example.yaml deleted file mode 100644 index c98c07a27..000000000 --- a/content/examples/config/config.example.yaml +++ /dev/null @@ -1,99 +0,0 @@ -# Main configuration flags : https://www.pomerium.com/docs/reference/ - -# -# address: ":8443" # optional, default is 443 -# service: "all" # optional, default is all -# log_level: info # optional, default is debug - -authenticate_service_url: https://authenticate.localhost.pomerium.io -# authorize service url will default to localhost in all-in-one mode, otherwise -# it should be set to a "behind-the-ingress" routable url -# authorize_service_url: https://pomerium-authorize-service.default.svc.cluster.local -# databroker service url defaults to http://localhost:5443 in all-in-one mode. -# Set it only when the databroker runs on another host/port (split/remote Core). -# databroker_service_url: https://pomerium-databroker-service.default.svc.cluster.local - -# Certificates can be loaded as files or base64 encoded bytes. -# certificate_file: "./cert.pem" # optional -# certificate_key_file: "./private-key.pem" # optional -# certificate_authority_file: "./cert.pem" - -# alternatively, insecure mode can be used if behind a TLS terminating ingress, -# or when using a sidecar proxy -# insecure_server: true - -# base64 encoded cert, eg. `base64 -i cert.pem` / `base64 -i private-key.pem` -# certificate: | -# "xxxxxx" -# certificate_key: | -# "xxxx" - -# Generate 256 bit random keys e.g. `head -c32 /dev/urandom | base64` -# shared_secret: hsJIQsx9KKx4qVlggg/T3AuLTmVu0uHhwTQgMPlVs7U= -# cookie_secret: WwMtDXWaRDMBQCylle8OJ+w4kLIDIGd8W3cB4/zFFtg= -# If set, a JWT based signature is appended to each request header `x-pomerium-jwt-assertion` -# signing_key: "Replace with base64'd private key from ./scripts/self-signed-sign-key.sh" - -# Identity Provider Settings - -# Auth0 -# idp_provider: "auth0" -# idp_provider_url: "https://REPLACE_ME.us.auth0.com" -# idp_client_id: "REPLACE_ME" # from the application the users login to -# idp_client_secret: "REPLACE_ME" # from the application the users login to -# the following is optional and only needed if you want role (Auth0 calls groups roles) data - -# Azure -# idp_provider: "azure" -# idp_provider_url: "https://login.microsoftonline.com/REPLACE_ME/v2.0" -# idp_client_id: "REPLACE_ME -# idp_client_secret: "REPLACE_ME" - -## GOOGLE -# idp_provider: "google" -# idp_client_id: "REPLACE_ME -# idp_client_secret: "REPLACE_ME - -# OKTA -# idp_provider: "okta" -# idp_client_id: "REPLACE_ME" -# idp_client_secret: "REPLACE_ME" -# idp_provider_url: "https://REPLACE_ME.oktapreview.com/oauth2/default" - -# OneLogin -# idp_provider: "onelogin" -# idp_client_id: "REPLACE_ME" -# idp_client_secret: "REPLACE_ME" -# idp_provider_url: "https://openid-connect.onelogin.com/oidc" #optional, defaults to `https://openid-connect.onelogin.com/oidc` - -# Proxied routes and per-route policies are defined in a routes block -routes: - - from: https://verify.localhost.pomerium.io - to: http://localhost:8000 - policy: - - allow: - or: - - domain: - is: pomerium.io - cors_allow_preflight: true - timeout: 30s - - from: https://external-verify.localhost.pomerium.io - to: https://verify.pomerium.com - policy: - - allow: - or: - - domain: - is: gmail.com - - from: https://weirdlyssl.localhost.pomerium.io - to: http://neverssl.com - policy: - - allow: - or: - - email: - is: user@example.com - - from: https://hello.localhost.pomerium.io - to: http://localhost:8080 - policy: - - allow: - or: - - claim/groups: "admins@pomerium.io" diff --git a/content/examples/config/config.minimal.env b/content/examples/config/config.minimal.env deleted file mode 100644 index 3b4099419..000000000 --- a/content/examples/config/config.minimal.env +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash - -# See : https://www.pomerium.com/docs/reference/certificates -export AUTOCERT=TRUE # Use Let's Encrypt to fetch certs. Port 80/443 must be internet accessible. - -# 256 bit random keys -export SHARED_SECRET="$(head -c32 /dev/urandom | base64)" -export COOKIE_SECRET="$(head -c32 /dev/urandom | base64)" diff --git a/content/examples/config/config.minimal.yaml.md b/content/examples/config/config.minimal.yaml.md deleted file mode 100644 index eda8337c3..000000000 --- a/content/examples/config/config.minimal.yaml.md +++ /dev/null @@ -1,35 +0,0 @@ -```yaml -# See detailed configuration settings : https://www.pomerium.com/docs/reference/ - -# this is the domain the identity provider will callback after a user authenticates -authenticate_service_url: https://authenticate.localhost.pomerium.io - -# certificate settings: https://www.pomerium.com/docs/reference/certificates.html -autocert: true -# REMOVE FOR PRODUCTION -autocert_use_staging: true - -# If you're using mkcert to test Pomerium locally, comment the autocert keys and uncomment -# the keys below, adjusting for your mkcert path: -# certificate_file: /home/user/.local/share/mkcert/rootCA.pem -# certificate_key_file: /user/alex/.local/share/mkcert/rootCA-key.pem - -# identity provider settings : https://www.pomerium.com/docs/integrations/user-identity/identity-providers.html -idp_provider: google -idp_client_id: REPLACE_ME -idp_client_secret: REPLACE_ME - -# Generate 256 bit random keys e.g. `head -c32 /dev/urandom | base64` -cookie_secret: WwMtDXWaRDMBQCylle8OJ+w4kLIDIGd8W3cB4/zFFtg= - -# https://pomerium.io/reference/#routes -routes: - - from: https://verify.localhost.pomerium.io - to: https://verify.pomerium.com - policy: - - allow: - or: - - email: - is: user@example.com - pass_identity_headers: true -``` diff --git a/content/examples/config/policy.example.yaml.md b/content/examples/config/policy.example.yaml.md deleted file mode 100644 index 059231385..000000000 --- a/content/examples/config/policy.example.yaml.md +++ /dev/null @@ -1,31 +0,0 @@ -```yaml -# This file contains only policy and route configuration details. Other -# configuration settings required by pomerium are excluded for clarity. -# See: https://www.pomerium.com/docs/reference/ - -# -# For a complete self contained configuration see : config.example.yaml. -# Or, mix and match a policy file (this) with env vars : config.example.env - -# Proxied routes and per-route policies are defined in a policy block -# NOTA BENE: You must uncomment the below 'policy' key if you are loading policy as a file. -# policy: -- from: https://verify.localhost.pomerium.io - to: http://localhost:8000 - allowed_domains: - - pomerium.io - cors_allow_preflight: true - timeout: 30s -- from: https://external-verify.localhost.pomerium.io - to: https://verify.pomerium.com - allowed_domains: - - gmail.com -- from: https://weirdlyssl.localhost.pomerium.io - to: http://neverssl.com - allowed_users: - - user@example.com -- from: https://hello.localhost.pomerium.io - to: http://localhost:8080 - allowed_users: - - user@example.com -``` diff --git a/content/examples/config/route.example.yaml.md b/content/examples/config/route.example.yaml.md index 85f8ca71f..eb0daee0f 100644 --- a/content/examples/config/route.example.yaml.md +++ b/content/examples/config/route.example.yaml.md @@ -1,11 +1,8 @@ ```yaml # This file contains only route and policy configuration details. Other -# configuration settings required by pomerium are excluded for clarity. -# See: https://www.pomerium.io/docs/reference/ - -# -# For a complete self contained configuration see : config.example.yaml. -# Or, mix and match a policy file (this) with env vars : config.example.env +# configuration settings required by Pomerium are excluded for clarity. +# See https://www.pomerium.com/docs/reference for the full configuration +# reference. routes: - from: https://verify.localhost.pomerium.io diff --git a/content/examples/docker/autocert.docker-compose.yml b/content/examples/docker/autocert.docker-compose.yml deleted file mode 100644 index 43bf75fbd..000000000 --- a/content/examples/docker/autocert.docker-compose.yml +++ /dev/null @@ -1,17 +0,0 @@ -services: - pomerium: - image: pomerium/pomerium:latest - environment: - # Generate new secret keys. e.g. `head -c32 /dev/urandom | base64` - - COOKIE_SECRET=V2JBZk0zWGtsL29UcFUvWjVDWWQ2UHExNXJ0b2VhcDI= - volumes: - # Use a volume to store ACME certificates - - pomerium:/data:rw - ports: - - 443:443 - - # https://verify.corp.beyondperimeter.com --> Pomerium --> http://verify - verify: - image: pomerium/verify:latest - expose: - - 80 diff --git a/content/examples/docker/basic.docker-compose.yml.md b/content/examples/docker/basic.docker-compose.yml.md deleted file mode 100644 index 722374cb8..000000000 --- a/content/examples/docker/basic.docker-compose.yml.md +++ /dev/null @@ -1,15 +0,0 @@ -```yaml -services: - pomerium: - image: pomerium/pomerium:latest - volumes: - ## Mount your config file: https://www.pomerium.com/docs/reference/ - - ./config.yaml:/pomerium/config.yaml:ro - ports: - - 443:443 - ## https://verify.localhost.pomerium.io --> Pomerium --> http://verify - verify: - image: pomerium/verify:latest - expose: - - 8000 -``` diff --git a/content/examples/docker/nginx.docker-compose.yml b/content/examples/docker/nginx.docker-compose.yml deleted file mode 100644 index c21c028a8..000000000 --- a/content/examples/docker/nginx.docker-compose.yml +++ /dev/null @@ -1,103 +0,0 @@ -services: - nginx: - image: pomerium/nginx-proxy:latest - ports: - - "443:443" - volumes: - # NOTE!!! : nginx must be supplied with your wildcard certificates. - # see : https://github.com/jwilder/nginx-proxy#wildcard-certificates - - ~/.acme.sh/*.corp.beyondperimeter.com_ecc/fullchain.cer:/etc/nginx/certs/corp.beyondperimeter.com.crt:ro - - ~/.acme.sh/*.corp.beyondperimeter.com_ecc/*.corp.beyondperimeter.com.key:/etc/nginx/certs/corp.beyondperimeter.com.key:ro - - /var/run/docker.sock:/tmp/docker.sock:ro - - pomerium-authenticate: - image: pomerium/pomerium:latest # or `build: .` to build from source - restart: always - environment: - - SERVICES=authenticate - - INSECURE_SERVER=TRUE - # NOTE!: Replace with your identity provider settings https://www.pomerium.com/docs/integrations/user-identity/identity-providers.html - # - IDP_PROVIDER=okta - # - IDP_PROVIDER_URL=https://beyondperimeter.okta.com - # - IDP_CLIENT_ID=REPLACE_ME - # - IDP_CLIENT_SECRET=REPLACE_ME - # NOTE! Generate new secret keys! e.g. `head -c32 /dev/urandom | base64` - # Generated secret keys must match between services - - SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M= - - COOKIE_SECRET=V2JBZk0zWGtsL29UcFUvWjVDWWQ2UHExNXJ0b2VhcDI= - # Tell nginx how to proxy pomerium's routes - - VIRTUAL_PROTO=http - - VIRTUAL_HOST=authenticate.corp.beyondperimeter.com - - VIRTUAL_PORT=443 - - DATABROKER_SERVICE_URL=http://pomerium-databroker:443 - volumes: - - ../config/config.example.yaml:/pomerium/config.yaml:ro - - expose: - - 443 - - pomerium-proxy: - image: pomerium/pomerium:latest # or `build: .` to build from source - restart: always - environment: - - SERVICES=proxy - - INSECURE_SERVER=TRUE - # IMPORTANT! If you are running pomerium behind another ingress (loadbalancer/firewall/etc) - # you must tell pomerium proxy how to communicate using an internal hostname for RPC - - AUTHORIZE_SERVICE_URL=http://pomerium-authorize:443 - # When communicating internally, rPC is going to get a name conflict expecting an external - # facing certificate name (i.e. authenticate-service.local vs *.corp.example.com). - - SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M= - - COOKIE_SECRET=V2JBZk0zWGtsL29UcFUvWjVDWWQ2UHExNXJ0b2VhcDI= - # Tell nginx how to proxy pomerium's routes - - VIRTUAL_PROTO=http - - VIRTUAL_HOST=*.corp.beyondperimeter.com - - VIRTUAL_PORT=443 - volumes: - - ../config/config.example.yaml:/pomerium/config.yaml:ro - expose: - - 443 - - pomerium-authorize: - image: pomerium/pomerium:latest # or `build: .` to build from source - restart: always - environment: - - SERVICES=authorize - - SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M= - - GRPC_INSECURE=TRUE - - GRPC_ADDRESS=:443 - - volumes: - # Retrieve non-secret config keys from the config file : https://www.pomerium.com/docs/reference/ - - # See `config.example.yaml` and modify to fit your needs. - - ../config/config.example.yaml:/pomerium/config.yaml:ro - expose: - - 443 - - pomerium-databroker: - image: pomerium/pomerium:latest # or `build: .` to build from source - restart: always - environment: - - SERVICES=databroker - - SHARED_SECRET=aDducXQzK2tPY3R4TmdqTGhaYS80eGYxcTUvWWJDb2M= - - GRPC_INSECURE=TRUE - - GRPC_ADDRESS=:443 - volumes: - # Retrieve non-secret config keys from the config file : https://www.pomerium.com/docs/reference/ - - # See `config.example.yaml` and modify to fit your needs. - - ../config/config.example.yaml:/pomerium/config.yaml:ro - expose: - - 443 - - # https://verify.corp.beyondperimeter.com - verify: - image: pomerium/verify:latest - expose: - - 80 - # https://hello.corp.beyondperimeter.com - hello: - image: gcr.io/google-samples/hello-app:1.0 - expose: - - 8080 diff --git a/content/examples/enterprise/hosted-auth-docker.yaml.md b/content/examples/enterprise/hosted-auth-docker.yaml.md index 5baab8004..d30a7ef5a 100644 --- a/content/examples/enterprise/hosted-auth-docker.yaml.md +++ b/content/examples/enterprise/hosted-auth-docker.yaml.md @@ -40,7 +40,7 @@ services: - metrics:/data:rw - ./console-config.yaml:/pomerium/console-config.yaml:ro database: - image: postgres:latest + image: postgres:16 restart: always healthcheck: test: ['CMD-SHELL', 'pg_isready -d postgres -U postgres'] diff --git a/content/examples/go-sdk/go-app.md b/content/examples/go-sdk/go-app.md index 31f3cf599..1d4e7dc45 100644 --- a/content/examples/go-sdk/go-app.md +++ b/content/examples/go-sdk/go-app.md @@ -9,7 +9,6 @@ import ( "fmt" "log" "net/http" - "time" "github.com/go-jose/go-jose/v3/jwt" "github.com/pomerium/sdk-go" diff --git a/content/examples/guacamole/guacamole.pomerium-config.md b/content/examples/guacamole/guacamole.pomerium-config.md index 4925db20c..084c56e38 100644 --- a/content/examples/guacamole/guacamole.pomerium-config.md +++ b/content/examples/guacamole/guacamole.pomerium-config.md @@ -1,10 +1,9 @@ ```yaml authenticate_service_url: https://authenticate.pomerium.app -jwt_claim_headers: email +jwt_claims_headers: email routes: - pass_identity_headers: true - from: https://guacamole.localhost.pomerium.io to: http://guacamole:8080 policy: diff --git a/content/examples/jenkins/jenkins-docker-compose.md b/content/examples/jenkins/jenkins-docker-compose.md index 8d11ed5de..de32d87d7 100644 --- a/content/examples/jenkins/jenkins-docker-compose.md +++ b/content/examples/jenkins/jenkins-docker-compose.md @@ -21,7 +21,7 @@ services: jenkins: networks: main: {} - image: jenkins/jenkins:lts-jdk11 + image: jenkins/jenkins:lts-jdk21 privileged: true user: root ports: @@ -31,5 +31,5 @@ services: # File path to Jenkins_home -- stores configs, build logs, and artifacts - ./home/jenkins_compose/jenkins_configuration:/var/jenkins_home # "sock" is the Unix socket the Docker daemon listens on by default - - ./var/run/docker.sock:/var/run/docker.sock + - /var/run/docker.sock:/var/run/docker.sock ``` diff --git a/content/examples/kubernetes/httpbin.yml b/content/examples/kubernetes/httpbin.yml deleted file mode 100644 index 51c5c4144..000000000 --- a/content/examples/kubernetes/httpbin.yml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: httpbin - labels: - app: httpbin -spec: - type: NodePort - ports: - - name: http - port: 8000 - targetPort: 80 - selector: - app: httpbin ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: httpbin -spec: - replicas: 1 - selector: - matchLabels: - app: httpbin - version: v1 - template: - metadata: - labels: - app: httpbin - version: v1 - spec: - containers: - - image: docker.io/kennethreitz/httpbin - imagePullPolicy: IfNotPresent - name: httpbin - ports: - - containerPort: 80 diff --git a/content/examples/kubernetes/ingress.nginx.yml b/content/examples/kubernetes/ingress.nginx.yml deleted file mode 100644 index 18669b065..000000000 --- a/content/examples/kubernetes/ingress.nginx.yml +++ /dev/null @@ -1,37 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: pomerium-ingress - annotations: - kubernetes.io/ingress.class: "nginx" - # kubernetes.io/tls-acme: "true" - # certmanager.k8s.io/issuer: "letsencrypt-prod" - # nginx.ingress.kubernetes.io/force-ssl-redirect: "true" - # nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - # nginx.ingress.kubernetes.io/proxy-buffer-size: "16k" - # to avoid ingress routing, enable - # nginx.ingress.kubernetes.io/ssl-passthrough: "true" - -spec: - tls: - - secretName: pomerium-tls - hosts: - - "*.corp.beyondperimeter.com" - - "authenticate.corp.beyondperimeter.com" - - rules: - - host: "*.corp.beyondperimeter.com" - http: - paths: - - paths: - backend: - serviceName: pomerium-proxy-service - servicePort: http - - - host: "authenticate.corp.beyondperimeter.com" - http: - paths: - - paths: - backend: - serviceName: pomerium-authenticate-service - servicePort: http diff --git a/content/examples/kubernetes/ingress.yml b/content/examples/kubernetes/ingress.yml deleted file mode 100644 index f6898dd40..000000000 --- a/content/examples/kubernetes/ingress.yml +++ /dev/null @@ -1,30 +0,0 @@ -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: pomerium-ingress - annotations: - kubernetes.io/ingress.allow-http: "false" - kubernetes.io/ingress.global-static-ip-name: pomerium - -spec: - tls: - - secretName: pomerium-tls - hosts: - - "*.corp.beyondperimeter.com" - - "authenticate.corp.beyondperimeter.com" - - rules: - - host: "*.corp.beyondperimeter.com" - http: - paths: - - paths: - backend: - serviceName: pomerium-proxy-service - servicePort: http - - host: "authenticate.corp.beyondperimeter.com" - http: - paths: - - paths: - backend: - serviceName: pomerium-authenticate-service - servicePort: http diff --git a/content/examples/kubernetes/istio/gateway.yml b/content/examples/kubernetes/istio/gateway.yml deleted file mode 100644 index 944c50062..000000000 --- a/content/examples/kubernetes/istio/gateway.yml +++ /dev/null @@ -1,41 +0,0 @@ -apiVersion: networking.istio.io/v1alpha3 -kind: Gateway -metadata: - name: internal-gateway - namespace: istio-system -spec: - selector: - istio: ingressgateway - servers: - - port: - number: 443 - protocol: HTTPS - name: https-default - tls: - mode: SIMPLE - serverCertificate: "sds" - privateKey: "sds" - credentialName: internal-cert - hosts: - - *.example.com ---- -apiVersion: cert-manager.io/v1alpha2 -kind: Certificate -metadata: - name: internal-cert - namespace: istio-system -spec: - secretName: internal-cert - issuerRef: - name: self-signed-issuer - kind: ClusterIssuer - commonName: *.example.com - dnsNames: - - *.example.com ---- -apiVersion: cert-manager.io/v1alpha2 -kind: ClusterIssuer -metadata: - name: self-signed-issuer -spec: - selfSigned: {} diff --git a/content/examples/kubernetes/istio/pomerium-helm-values.yml b/content/examples/kubernetes/istio/pomerium-helm-values.yml deleted file mode 100644 index cc09fc5de..000000000 --- a/content/examples/kubernetes/istio/pomerium-helm-values.yml +++ /dev/null @@ -1,13 +0,0 @@ -config: - insecure: true - policy: - - from: https://grafana.example.com - to: "http://prometheus-grafana.monitoring.svc.cluster.local" - timeout: 30s - allowed_domains: - - example.com -ingress: - enabled: false - -extraEnv: - JWT_CLAIMS_HEADERS: email diff --git a/content/examples/kubernetes/istio/service-entry.yml b/content/examples/kubernetes/istio/service-entry.yml deleted file mode 100644 index c4f21f241..000000000 --- a/content/examples/kubernetes/istio/service-entry.yml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: networking.istio.io/v1alpha3 -kind: ServiceEntry -metadata: - name: external-idp - namespace: pomerium -spec: - hosts: - - example.okta.com - location: MESH_EXTERNAL - ports: - - number: 443 - name: https - protocol: TLS - resolution: DNS diff --git a/content/examples/kubernetes/istio/virtual-services.yml b/content/examples/kubernetes/istio/virtual-services.yml deleted file mode 100644 index 4c6066dfd..000000000 --- a/content/examples/kubernetes/istio/virtual-services.yml +++ /dev/null @@ -1,34 +0,0 @@ -apiVersion: networking.istio.io/v1beta1 -kind: VirtualService -metadata: - name: grafana-virtual-service - namespace: pomerium -spec: - gateways: - - istio-system/internal-gateway - hosts: - - grafana.example.com - http: - - route: - - destination: - host: pomerium-proxy - port: - number: 80 ---- -apiVersion: networking.istio.io/v1beta1 -kind: VirtualService -metadata: - name: authenticate-virtual-service - namespace: pomerium -spec: - gateways: - - istio-system/internal-gateway - hosts: - - authenticate.example.com - http: - - route: - - destination: - host: pomerium-authenticate - port: - number: 80 ---- diff --git a/content/examples/kubernetes/kubernetes-config.yaml b/content/examples/kubernetes/kubernetes-config.yaml deleted file mode 100644 index 571063582..000000000 --- a/content/examples/kubernetes/kubernetes-config.yaml +++ /dev/null @@ -1,25 +0,0 @@ -# Main configuration flags : https://www.pomerium.com/docs/reference/ - -insecure_server: true -grpc_insecure: true -address: ":80" -grpc_address: ":80" - -authenticate_service_url: https://authenticate.localhost.pomerium.io -authorize_service_url: http://pomerium-authorize-service.default.svc.cluster.local -databroker_service_url: http://pomerium-databroker-service.default.svc.cluster.local - -override_certificate_name: "*.localhost.pomerium.io" - -idp_provider: google -idp_client_id: REPLACE_ME -idp_client_secret: "REPLACE_ME" - -routes: - - from: https://verify.localhost.pomerium.io - to: http://httpbin.default.svc.cluster.local:8000 - policy: - - allow: - or: - - domain: - is: gmail.com diff --git a/content/examples/kubernetes/kubernetes_gke.sh b/content/examples/kubernetes/kubernetes_gke.sh deleted file mode 100755 index ea9f96a8d..000000000 --- a/content/examples/kubernetes/kubernetes_gke.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -# NOTE! This will create real resources on Google GCP. Make sure you clean up any unused -# resources to avoid being billed. -# For reference, this tutorial cost ~10 cents for a couple of hours. -# NOTE! You must change the identity provider client secret setting in your config file! -# cSpell:ignore fullchain - -echo "=> creating cluster" -gcloud container clusters create pomerium --num-nodes 3 --region us-west2 - -echo "=> get cluster credentials so we can use kubectl locally" -gcloud container clusters get-credentials pomerium --region us-west2 - -echo "=> create config from kubernetes-config.yaml which we will mount" -kubectl create configmap config --from-file="config.yaml"="kubernetes-config.yaml" - -echo "=> create our random shared-secret and cookie-secret keys as env vars" -kubectl create secret generic shared-secret --from-literal=shared-secret=$(head -c32 /dev/urandom | base64) -kubectl create secret generic cookie-secret --from-literal=cookie-secret=$(head -c32 /dev/urandom | base64) - -echo "=> initialize secrets for TLS wild card for service use" -kubectl create secret generic certificate \ - --from-literal=certificate=$(base64 -i "$HOME/.acme.sh/*.corp.beyondperimeter.com_ecc/fullchain.cer") -kubectl create secret generic certificate-key \ - --from-literal=certificate-key=$(base64 -i "$HOME/.acme.sh/*.corp.beyondperimeter.com_ecc/*.corp.beyondperimeter.com.key") - -echo "=> load TLS to ingress" -kubectl create secret tls pomerium-tls \ - --key "$HOME/.acme.sh/*.corp.beyondperimeter.com_ecc/*.corp.beyondperimeter.com.key" \ - --cert "$HOME/.acme.sh/*.corp.beyondperimeter.com_ecc/fullchain.cer" - -echo "=> deploy pomerium proxy, authorize, and authenticate" -kubectl apply -f pomerium-proxy.yml -kubectl apply -f pomerium-authenticate.yml -kubectl apply -f pomerium-authorize.yml -kubectl apply -f pomerium-databroker.yml - -echo "=> deploy our test app, httpbin" -kubectl apply -f httpbin.yml - -echo "=> deploy the GKE specific ingress" -kubectl apply -f ingress.yml - -# Alternatively, nginx-ingress can be used -# kubectl apply -f ingress.nginx.yml - -# When done, clean up by deleting the cluster! -# gcloud container clusters delete pomerium diff --git a/content/examples/kubernetes/kubernetes_nginx.sh b/content/examples/kubernetes/kubernetes_nginx.sh deleted file mode 100644 index 8ffa6a5a6..000000000 --- a/content/examples/kubernetes/kubernetes_nginx.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -echo "=> create config from kubernetes-config.yaml which we will mount" -kubectl create configmap config --from-file="config.yaml"="kubernetes-config.yaml" - -echo "=> create our random shared-secret and cookie-secret keys as env vars" -kubectl create secret generic shared-secret --from-literal=shared-secret=$(head -c32 /dev/urandom | base64) -kubectl create secret generic cookie-secret --from-literal=cookie-secret=$(head -c32 /dev/urandom | base64) - -echo "=> deploy pomerium proxy, authorize, and authenticate" -kubectl apply -f pomerium-proxy.yml -kubectl apply -f pomerium-authenticate.yml -kubectl apply -f pomerium-authorize.yml - -echo "=> deploy our test app, httpbin" -kubectl apply -f httpbin.yml - -echo "=> deploy nginx-ingress" -kubectl apply -f ingress.yml diff --git a/content/examples/kubernetes/pomerium-authenticate.yml b/content/examples/kubernetes/pomerium-authenticate.yml deleted file mode 100644 index bc2647b93..000000000 --- a/content/examples/kubernetes/pomerium-authenticate.yml +++ /dev/null @@ -1,69 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pomerium-authenticate-service -spec: - ports: - - port: 80 - name: http - selector: - app: pomerium-authenticate - type: NodePort ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: pomerium-authenticate - labels: - app: pomerium-authenticate -spec: - replicas: 1 - selector: - matchLabels: - app: pomerium-authenticate - template: - metadata: - labels: - app: pomerium-authenticate - spec: - containers: - - image: pomerium/pomerium:latest - name: pomerium-authenticate - args: - - --config=/etc/pomerium/config.yaml - ports: - - containerPort: 80 - name: http - protocol: TCP - env: - - name: SERVICES - value: authenticate - - name: SHARED_SECRET - valueFrom: - secretKeyRef: - name: shared-secret - key: shared-secret - - name: COOKIE_SECRET - valueFrom: - secretKeyRef: - name: cookie-secret - key: cookie-secret - readinessProbe: - httpGet: - path: /ping - port: 80 - scheme: HTTP - livenessProbe: - httpGet: - path: /ping - port: 80 - scheme: HTTP - initialDelaySeconds: 5 - timeoutSeconds: 1 - volumeMounts: - - mountPath: /etc/pomerium/ - name: config - volumes: - - name: config - configMap: - name: config diff --git a/content/examples/kubernetes/pomerium-authorize.yml b/content/examples/kubernetes/pomerium-authorize.yml deleted file mode 100644 index c6d7ee81a..000000000 --- a/content/examples/kubernetes/pomerium-authorize.yml +++ /dev/null @@ -1,63 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pomerium-authorize-service -spec: - ports: - - port: 80 - name: grpc - selector: - app: pomerium-authorize - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: pomerium-authorize - labels: - app: pomerium-authorize -spec: - replicas: 1 - selector: - matchLabels: - app: pomerium-authorize - template: - metadata: - labels: - app: pomerium-authorize - spec: - containers: - - image: pomerium/pomerium:latest - name: pomerium-authorize - args: - - --config=/etc/pomerium/config.yaml - ports: - - containerPort: 80 - name: grpc - protocol: TCP - env: - - name: SERVICES - value: authorize - - name: SHARED_SECRET - valueFrom: - secretKeyRef: - name: shared-secret - key: shared-secret - readinessProbe: - tcpSocket: - port: 80 - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - tcpSocket: - port: 80 - initialDelaySeconds: 15 - periodSeconds: 20 - - volumeMounts: - - mountPath: /etc/pomerium/ - name: config - volumes: - - name: config - configMap: - name: config diff --git a/content/examples/kubernetes/pomerium-certificates.yaml.md b/content/examples/kubernetes/pomerium-certificates.yaml.md index ded940a0e..22593ca9a 100644 --- a/content/examples/kubernetes/pomerium-certificates.yaml.md +++ b/content/examples/kubernetes/pomerium-certificates.yaml.md @@ -1,4 +1,4 @@ -```yaml title="pomerium-console-certificate.yaml" +```yaml title="pomerium-certificates.yaml" apiVersion: cert-manager.io/v1 kind: Certificate metadata: diff --git a/content/examples/kubernetes/pomerium-console-certificate.yaml b/content/examples/kubernetes/pomerium-console-certificate.yaml deleted file mode 100644 index 1b5d7f2e6..000000000 --- a/content/examples/kubernetes/pomerium-console-certificate.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: pomerium-console-cert - namespace: pomerium -spec: - secretName: pomerium-console-tls - issuerRef: - name: pomerium-issuer - kind: Issuer - dnsNames: - - pomerium-console.pomerium.svc.cluster.local diff --git a/content/examples/kubernetes/pomerium-databroker.yml b/content/examples/kubernetes/pomerium-databroker.yml deleted file mode 100644 index fa7eabaaa..000000000 --- a/content/examples/kubernetes/pomerium-databroker.yml +++ /dev/null @@ -1,64 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pomerium-databroker-service -spec: - clusterIP: None # databroker is a headless service! - ports: - - port: 80 - name: grpc - selector: - app: pomerium-databroker - type: ClusterIP ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: pomerium-databroker - labels: - app: pomerium-databroker -spec: - replicas: 1 - selector: - matchLabels: - app: pomerium-databroker - template: - metadata: - labels: - app: pomerium-databroker - spec: - containers: - - image: pomerium/pomerium:latest - name: pomerium-databroker - args: - - --config=/etc/pomerium/config.yaml - ports: - - containerPort: 80 - name: grpc - protocol: TCP - env: - - name: SERVICES - value: databroker - - name: SHARED_SECRET - valueFrom: - secretKeyRef: - name: shared-secret - key: shared-secret - readinessProbe: - tcpSocket: - port: 80 - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - tcpSocket: - port: 80 - initialDelaySeconds: 15 - periodSeconds: 20 - - volumeMounts: - - mountPath: /etc/pomerium/ - name: config - volumes: - - name: config - configMap: - name: config diff --git a/content/examples/kubernetes/pomerium-proxy.yml b/content/examples/kubernetes/pomerium-proxy.yml deleted file mode 100644 index f58e827d3..000000000 --- a/content/examples/kubernetes/pomerium-proxy.yml +++ /dev/null @@ -1,71 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: pomerium-proxy-service -spec: - ports: - - port: 80 - protocol: TCP - name: http - targetPort: http - selector: - app: pomerium-proxy - type: NodePort ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: pomerium-proxy - labels: - app: pomerium-proxy -spec: - replicas: 1 - selector: - matchLabels: - app: pomerium-proxy - template: - metadata: - labels: - app: pomerium-proxy - spec: - containers: - - image: pomerium/pomerium:latest - name: pomerium-proxy - args: - - --config=/etc/pomerium/config.yaml - ports: - - containerPort: 80 - name: http - protocol: TCP - env: - - name: SERVICES - value: proxy - - name: SHARED_SECRET - valueFrom: - secretKeyRef: - name: shared-secret - key: shared-secret - - name: COOKIE_SECRET - valueFrom: - secretKeyRef: - name: cookie-secret - key: cookie-secret - readinessProbe: - httpGet: - path: /ping - port: 80 - scheme: HTTP - livenessProbe: - httpGet: - path: /ping - port: 80 - scheme: HTTP - initialDelaySeconds: 10 - timeoutSeconds: 1 - volumeMounts: - - mountPath: /etc/pomerium/ - name: config - volumes: - - name: config - configMap: - name: config diff --git a/content/examples/kubernetes/pomerium-values.yaml.md b/content/examples/kubernetes/pomerium-values.yaml.md index 0d914e6d8..383235763 100644 --- a/content/examples/kubernetes/pomerium-values.yaml.md +++ b/content/examples/kubernetes/pomerium-values.yaml.md @@ -16,7 +16,7 @@ proxy: databroker: existingTLSSecret: pomerium-tls storage: - connectionString: postgres://://postgres.pomerium.svc.cluster.local #Replace with the path to your DB solution. + connectionString: postgres://USER:PASSWORD@postgres.pomerium.svc.cluster.local:5432/postgres # Replace with the path to your DB solution. type: postgres clientTLS: existingSecretName: pomerium-tls diff --git a/content/examples/kubernetes/values.yaml b/content/examples/kubernetes/values.yaml deleted file mode 100644 index 55a1ba29d..000000000 --- a/content/examples/kubernetes/values.yaml +++ /dev/null @@ -1,27 +0,0 @@ -authenticate: - idp: - provider: "google" - clientID: YOUR_CLIENT_ID - clientSecret: YOUR_SECRET - service: - type: NodePort - annotations: - cloud.google.com/app-protocols: '{"https":"HTTPS"}' - -proxy: - service: - type: NodePort - annotations: - cloud.google.com/app-protocols: '{"https":"HTTPS"}' - -config: - rootDomain: localhost.pomerium.io - policy: - - from: https://hello.localhost.pomerium.io - to: http://nginx.default.svc.cluster.local:80 - allowed_domains: - - gmail.com - -ingress: - annotations: - kubernetes.io/ingress.allow-http: "false" diff --git a/content/examples/mutual-tls/.dockerignore b/content/examples/mutual-tls/.dockerignore new file mode 100644 index 000000000..aca157f16 --- /dev/null +++ b/content/examples/mutual-tls/.dockerignore @@ -0,0 +1,9 @@ +out/ +.env +.git +.gitignore +.dockerignore +README.md +docker-compose.yaml +example.config.yaml +scripts/ diff --git a/content/examples/mutual-tls/.gitignore b/content/examples/mutual-tls/.gitignore new file mode 100644 index 000000000..ccf91bad4 --- /dev/null +++ b/content/examples/mutual-tls/.gitignore @@ -0,0 +1,2 @@ +out/ +.env diff --git a/content/examples/mutual-tls/Dockerfile b/content/examples/mutual-tls/Dockerfile new file mode 100644 index 000000000..dc4ac41be --- /dev/null +++ b/content/examples/mutual-tls/Dockerfile @@ -0,0 +1,13 @@ +FROM golang:1.26.2-bookworm@sha256:4f4ab2c90005e7e63cb631f0b4427f05422f241622ee3ec4727cc5febbf83e34 AS build-env + +WORKDIR /go/src/app +COPY . /go/src/app + +RUN go mod download +RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /app . + +FROM gcr.io/distroless/static:nonroot@sha256:e3f945647ffb95b5839c07038d64f9811adf17308b9121d8a2b87b6a22a80a39 +COPY --from=build-env /app /app +USER nonroot:nonroot +EXPOSE 8443 +CMD ["/app"] diff --git a/content/examples/mutual-tls/README.md b/content/examples/mutual-tls/README.md new file mode 100644 index 000000000..90ea9cb40 --- /dev/null +++ b/content/examples/mutual-tls/README.md @@ -0,0 +1,80 @@ +# Mutual Authenticated TLS Example + +A tiny Go HTTP server that enforces client certificates and can be used to test +mutual TLS with Pomerium. + +## What this demonstrates + +Two things: + +1. A standalone mTLS-protected upstream (`mtls`) that requires a client + certificate signed by a trusted CA. You can hit it directly with `curl`. +2. A reference Pomerium configuration that proxies to that upstream while + presenting its own client certificate (`tls_client_cert_file`) and + verifying the upstream against a custom CA (`tls_custom_ca_file`). + +The end-to-end demo path (`docker compose up mtls` + `./scripts/curl.sh`) +exercises (1) directly. (2) is a configuration reference; running Pomerium +end-to-end requires your own identity provider credentials and external TLS. + +## Quick start + +Prerequisites: Docker and [`certstrap`](https://github.com/square/certstrap). + +```bash +./scripts/generate_certs.sh # wipes and recreates ./out/, writes ./.env +docker compose up mtls -d # builds the Go server and runs it on :8443 +./scripts/curl.sh # mTLS round-trip against the running server +``` + +`./out/` and `./.env` are generated on demand and gitignored. Re-running +`generate_certs.sh` deletes any existing `./out/` first so re-runs produce +clean state. The script runs under `umask 077`, so the `out/` directory and +`./.env` land at `0600` (and certstrap writes its own files at `0400`, +which is also owner-only and therefore consistent with the umask). + +If you run the reference `pomerium` Compose service (`docker compose +--profile reference up`), the container reads three specific cert/key files +that are bind-mounted individually from `./out`: `good-ca.crt`, +`pomerium.crt`, and `pomerium.key`. The CA private keys and the curl test +client keys stay on the host. On Linux, the default Pomerium image runs as +a non-root user (`nonroot`, UID 65532) and the `0400`/`0600` files won't be +readable through a bind mount that preserves host ownership. Either relax +the perms on just the three mounted files (`chmod a+r out/good-ca.crt +out/pomerium.crt out/pomerium.key`), or run the container with a `user:` +matching your local owner. Docker Desktop and OrbStack on macOS remap +bind-mount ownership to the container user, so this is not an issue on +those platforms. + +## Files + +- `main.go` — the Go HTTP server that enforces client certs. +- `Dockerfile` — multi-stage build of the Go server into a distroless image. +- `docker-compose.yaml` — runs the `mtls` server (and optionally a reference + Pomerium service that proxies to it). +- `example.config.yaml` — Pomerium config showing how to route through to an + mTLS upstream using + `tls_custom_ca_file`/`tls_client_cert_file`/`tls_client_key_file`. Replace + the `REPLACE_ME` identity-provider values and the `corp.domain.example` + hostnames before running Pomerium. +- `scripts/generate_certs.sh` — generates a good CA, a bad CA, a Pomerium + client cert, a server cert (with SANs for `localhost`, `web-app`, and the + `mtls` Compose service name), and good/bad client certs for the curl + tests. Also writes a `.env` file the Compose `mtls` service consumes. +- `scripts/curl.sh` — exercises the running mTLS server with the good client + cert; commented variants demonstrate the rejection paths. + +## Running Pomerium against the mTLS upstream + +The `pomerium` service in `docker-compose.yaml` is a reference, not a working +demo. To wire it up end-to-end you need: + +- Real `CERTIFICATE` / `CERTIFICATE_KEY` env vars for Pomerium's external TLS + (or use `autocert: true` and an externally reachable hostname). +- A `COOKIE_SECRET` (32 bytes base64). +- Working identity-provider credentials in `example.config.yaml`. +- DNS for `mtls.corp.domain.example` (or whatever you change it to) pointing + at the host running Pomerium. + +Pomerium will read its upstream client cert / key / CA from +`/pomerium/out/*.crt`, mounted from `./out` in this directory. diff --git a/content/examples/mutual-tls/docker-compose.yaml b/content/examples/mutual-tls/docker-compose.yaml new file mode 100644 index 000000000..f003ad057 --- /dev/null +++ b/content/examples/mutual-tls/docker-compose.yaml @@ -0,0 +1,30 @@ +services: + # Reference Pomerium service. Requires real CERTIFICATE / CERTIFICATE_KEY / + # COOKIE_SECRET and working IdP credentials in example.config.yaml; left + # behind a Compose profile so it doesn't auto-start and crash-loop during + # the basic curl-against-mtls demo. + pomerium: + image: pomerium/pomerium:latest + profiles: + - reference + environment: + - CERTIFICATE + - CERTIFICATE_KEY + - COOKIE_SECRET + # Mount only the specific certs Pomerium needs for the upstream connection. + # Mounting the whole ./out/ directory would expose CA private keys and the + # curl test client keys that don't belong inside this container. + volumes: + - ./example.config.yaml:/pomerium/config.yaml:ro + - ./out/good-ca.crt:/pomerium/out/good-ca.crt:ro + - ./out/pomerium.crt:/pomerium/out/pomerium.crt:ro + - ./out/pomerium.key:/pomerium/out/pomerium.key:ro + ports: + - 443:443 + + mtls: + build: . + env_file: + - ./.env + ports: + - 8443:8443 diff --git a/content/examples/mutual-tls/example.config.yaml b/content/examples/mutual-tls/example.config.yaml new file mode 100644 index 000000000..9b75c3a96 --- /dev/null +++ b/content/examples/mutual-tls/example.config.yaml @@ -0,0 +1,26 @@ +# See detailed configuration settings : https://www.pomerium.com/docs/reference +authenticate_service_url: https://authenticate.corp.domain.example +authorize_service_url: https://authorize.corp.domain.example + +# identity provider settings : https://www.pomerium.com/docs/identity-providers +idp_provider: google +idp_client_id: REPLACE_ME +idp_client_secret: REPLACE_ME + +routes: + - from: https://mtls.corp.domain.example + to: https://mtls:8443 + policy: + - allow: + or: + - domain: + is: domain.example + # Verifies the upstream's server cert was issued by this CA. + tls_custom_ca_file: /pomerium/out/good-ca.crt + # Presented to the upstream when the upstream demands a client cert. + tls_client_cert_file: /pomerium/out/pomerium.crt + tls_client_key_file: /pomerium/out/pomerium.key + + - from: https://verify.corp.domain.example + to: https://verify.pomerium.com + allow_public_unauthenticated_access: true diff --git a/content/examples/mutual-tls/go.mod b/content/examples/mutual-tls/go.mod new file mode 100644 index 000000000..0c7e8736c --- /dev/null +++ b/content/examples/mutual-tls/go.mod @@ -0,0 +1,3 @@ +module github.com/pomerium/documentation/content/examples/mutual-tls + +go 1.26 diff --git a/content/examples/mutual-tls/main.go b/content/examples/mutual-tls/main.go new file mode 100644 index 000000000..ddfa9efdd --- /dev/null +++ b/content/examples/mutual-tls/main.go @@ -0,0 +1,141 @@ +package main + +import ( + "crypto/tls" + "crypto/x509" + "encoding/base64" + "fmt" + "log" + "net" + "net/http" + "os" + "strings" + "time" +) + +func main() { + port := "8443" + if fromEnv := os.Getenv("PORT"); fromEnv != "" { + port = fromEnv + } + tlsCert := os.Getenv("TLS_CERT") + tlsKey := os.Getenv("TLS_KEY") + clientCA := os.Getenv("CLIENT_CA") + + if tlsCert == "" { + log.Fatal("TLS_CERT environment variable must be set") + } + if tlsKey == "" { + log.Fatal("TLS_KEY environment variable must be set") + } + if clientCA == "" { + log.Fatal("CLIENT_CA environment variable must be set") + } + mux := http.NewServeMux() + mux.HandleFunc("/", hello) + srv := &http.Server{ + Handler: mux, + ReadHeaderTimeout: 5 * time.Second, + ReadTimeout: 10 * time.Second, + WriteTimeout: 10 * time.Second, + IdleTimeout: 60 * time.Second, + ErrorLog: log.New(os.Stderr, "", log.LstdFlags), + } + ln, err := newClientCertTLSListener(":"+port, tlsCert, tlsKey, clientCA) + if err != nil { + log.Fatalf("failed creating tls listener: %v", err) + } + log.Printf("listening on port %s", port) + if err := srv.Serve(ln); err != nil && err != http.ErrServerClosed { + log.Fatalf("serve: %v", err) + } +} + +func hello(w http.ResponseWriter, r *http.Request) { + log.Printf("Serving request: %s %s", r.Method, r.URL.Path) + fmt.Fprintf(w, "Hello, world!\n") + fmt.Fprintf(w, "%s %s %s\n", r.Method, r.URL, r.Proto) + fmt.Fprintf(w, "TLS\n\tServerName: %s\n\tVersion: %d\n\tCipherSuite: %d\n", + r.TLS.ServerName, r.TLS.Version, r.TLS.CipherSuite) + + for _, cert := range r.TLS.PeerCertificates { + fmt.Fprintf(w, "TLSPeerCertificate: Subject %+v\n", cert.Subject) + } + + fmt.Fprintf(w, "Headers\n") + for k, v := range r.Header { + // Redact sensitive headers in the demo response so screenshots and + // shared logs don't accidentally leak bearer tokens, cookies, or the + // JWT assertion Pomerium injects. + if isSensitiveHeader(k) { + fmt.Fprintf(w, "\t[%s]:\n\t\t[redacted]\n", k) + continue + } + fmt.Fprintf(w, "\t[%s]:\n\t\t%s\n", k, strings.Join(v, ", ")) + } +} + +func isSensitiveHeader(name string) bool { + switch strings.ToLower(name) { + case "authorization", "cookie", "x-pomerium-jwt-assertion": + return true + } + return false +} + +func newClientCertTLSListener(addr, tlsCert, tlsKey, clientCA string) (net.Listener, error) { + caPool, err := decodeCertPoolFromPEM(clientCA) + if err != nil { + return nil, err + } + cert, err := decodeCertificate(tlsCert, tlsKey) + if err != nil { + return nil, err + } + + // TLS 1.3 only — Go's stdlib manages the cipher and curve list; pinning + // either field on a public reference example freezes a list that ages + // poorly. tls.VersionTLS13 ignores CipherSuites and CurvePreferences. + tlsConfig := &tls.Config{ + ClientAuth: tls.RequireAndVerifyClientCert, + ClientCAs: caPool, + MinVersion: tls.VersionTLS13, + Certificates: []tls.Certificate{cert}, + NextProtos: []string{"h2"}, + } + + ln, err := net.Listen("tcp", addr) + if err != nil { + return nil, err + } + + return tls.NewListener(ln, tlsConfig), nil +} + +func decodeCertPoolFromPEM(encPemCerts string) (*x509.CertPool, error) { + pemCerts, err := base64.StdEncoding.DecodeString(encPemCerts) + if err != nil { + return nil, fmt.Errorf("decode CA pem: %w", err) + } + certPool := x509.NewCertPool() + if ok := certPool.AppendCertsFromPEM(pemCerts); !ok { + return nil, fmt.Errorf("append CA certs from pem") + } + return certPool, nil +} + +func decodeCertificate(cert, key string) (tls.Certificate, error) { + decodedCert, err := base64.StdEncoding.DecodeString(cert) + if err != nil { + return tls.Certificate{}, fmt.Errorf("decode cert: %w", err) + } + decodedKey, err := base64.StdEncoding.DecodeString(key) + if err != nil { + return tls.Certificate{}, fmt.Errorf("decode key: %w", err) + } + pair, err := tls.X509KeyPair(decodedCert, decodedKey) + if err != nil { + return tls.Certificate{}, fmt.Errorf("X509KeyPair: %w", err) + } + return pair, nil +} diff --git a/content/examples/mutual-tls/scripts/curl.sh b/content/examples/mutual-tls/scripts/curl.sh new file mode 100755 index 000000000..b22d4c509 --- /dev/null +++ b/content/examples/mutual-tls/scripts/curl.sh @@ -0,0 +1,22 @@ +#!/bin/bash +set -euo pipefail +cd "$(dirname "$0")/.." + +# A valid client cert: should return 200. +curl -v \ + --cacert out/good-ca.crt \ + --key out/good-curl.key \ + --cert out/good-curl.crt \ + https://127.0.0.1:8443 + +# Other paths to try manually: +# +# Untrusted server CA, good client cert (rejected by curl): +# curl -v --cacert out/bad-ca.crt \ +# --key out/good-curl.key --cert out/good-curl.crt \ +# https://127.0.0.1:8443 +# +# Untrusted client cert from a CA the server doesn't trust (rejected by server): +# curl -v --cacert out/good-ca.crt \ +# --key out/bad-curl.key --cert out/bad-curl.crt \ +# https://127.0.0.1:8443 diff --git a/content/examples/mutual-tls/scripts/generate_certs.sh b/content/examples/mutual-tls/scripts/generate_certs.sh new file mode 100755 index 000000000..f10515c0e --- /dev/null +++ b/content/examples/mutual-tls/scripts/generate_certs.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# https://github.com/square/certstrap +set -euo pipefail + +# Restrict permissions on every file we create from here on. certstrap and +# the .env writer both inherit this umask, so private keys land at 0600. +umask 077 + +cd "$(dirname "$0")/.." + +# Clean any prior output so re-runs start fresh. +rm -rf -- ./out +mkdir -p out + +certstrap --depot-path out init --passphrase "" --common-name good-ca +certstrap --depot-path out init --passphrase "" --common-name bad-ca + +# pomerium client cert (used by Pomerium to authenticate upstream to mtls). +certstrap --depot-path out request-cert --passphrase "" --common-name pomerium +certstrap --depot-path out sign pomerium --CA good-ca + +# downstream app server cert; SANs cover localhost (curl direct) and the +# Compose service name "mtls" (Pomerium → mtls upstream). +certstrap --depot-path out request-cert --passphrase "" \ + -ip 127.0.0.1 -domain web-app,localhost,mtls +certstrap --depot-path out sign web-app --CA good-ca + +# good-curl: client cert signed by good-ca, accepted by the mtls server. +certstrap --depot-path out request-cert --passphrase "" --common-name good-curl +certstrap --depot-path out sign good-curl --CA good-ca + +# bad-curl: client cert signed by bad-ca, rejected by the mtls server. +certstrap --depot-path out request-cert --passphrase "" --common-name bad-curl +certstrap --depot-path out sign bad-curl --CA bad-ca + +# Emit a .env file consumed by docker-compose for the mtls service. Compose +# expects TLS_CERT/TLS_KEY/CLIENT_CA as base64-encoded blobs. +{ + printf 'TLS_CERT=%s\n' "$(base64 < out/web-app.crt | tr -d '\n')" + printf 'TLS_KEY=%s\n' "$(base64 < out/web-app.key | tr -d '\n')" + printf 'CLIENT_CA=%s\n' "$(base64 < out/good-ca.crt | tr -d '\n')" +} > .env + +echo "Generated certs in ./out/ and env vars in ./.env" diff --git a/content/examples/nginx/README.md b/content/examples/nginx/README.md deleted file mode 100644 index 989335427..000000000 --- a/content/examples/nginx/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Pomerium as external auth provider for Nginx - -Run this demo locally on your docker-compose capable workstation, or replace `localhost.pomerium.io` with your own domain if running on a server. - -## Includes - -- Authentication and Authorization managed by pomerium -- Routing / reverse proxying handled by nginx - -## How - -- Update `config.yaml` for your e-mail address, if not using gmail/google. -- Replace secrets in `config.yaml`. -- Run `docker-compose up` from this directory. -- Navigate to `https://verify.localhost.pomerium.io` -- ??? -- Profit diff --git a/content/examples/nginx/_wildcard.localhost.pomerium.io-key.pem b/content/examples/nginx/_wildcard.localhost.pomerium.io-key.pem deleted file mode 100644 index 2ad75e316..000000000 --- a/content/examples/nginx/_wildcard.localhost.pomerium.io-key.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDXfeTmeNmQFK3r -CrLcdh9pVrsSjbNOAP2BIQ3AfGdf/S0UqjU1UhXOb2gLm5Dsj/vFvs/fSkiahBdj -7zR1dh7jdOnf3QgcAjIMTo7sJggsABHBF0vHVMXJtNoWmZ+AYOirsn22N3EoUNmX -jlr19LnW07DtkHJFPYsYFy01uOEKGbzKQh8E6DFv3tPNp/raUHkGSAUpT11tZcdf -vbSHuSN4xzGOs6T9QCnu0wCGb2MJNa8l5dhtVuy59jcZWM2i4EBLnXsYbHhkg/uZ -xnVfm3YxgNM8bA2T1DqSUxjpLt7Dty9MHBaEyHVrH/nXYluF1wI7jNC2A7dE6VKq -AkSmFKG7AgMBAAECggEARCYmW9TgSTahAfIyOpKIwJGTO/zgNc0OXuYLKVKuhqbU -uPJTPXemOdD1wKYEISwv3YvIxb8CUwtvMkWV+4fNoPV6eTe3ttPi7A10Ga61auTi -uIQbjQB8RJwTVI5k6P681n/uTdAe0zcueUWl8p7gntX34EmMOeWKtaWuwIylbsG8 -Ftvls8dI/soHUBgZT9HHo3ZitaRQtDYN+YjqAWfQCtPFrBJ5TPS9W6z3cmB/2l19 -nkwZljomj+mJZseEStQUOH/YXf7jpZCWNuxj9l9C+/F5pmiQX6w87thohVXFPmXx -zEExPHePvThx4CxrUGyBeWfzUaYMfzx1T/gyMixDYQKBgQD642G2ElXQSnlZZoLf -gMYTazAjtv7PIRVcVjOJfUORx5LP4sV7CkWokIMdbzfiVkerWt6kb2HDhBskvdFW -ag6Fl8t/Miyi+ZTrE/PmZJqs7fGtmSqjY8wWKfcN6gyTPkh789DXU7ddJIiJLQ10 -sf5Mg2sQkMLQo5XnnauV/SmKiQKBgQDb4eL/MmSR7yKnjxjvek7xXJGqaEXBmazn -pUhp6B+7aHsAg/u71DjzirMn2Ra3+WQ+sDQwbkMQuokqBPUij0Bcv61QSaocjrnb -PmwtXlHeyk9RnGj60oW55gIuJw0EseI17IaqHJPyDNVCQ9WJteI4y8Da+m0E5ohZ -udXzk9DpIwKBgCK3xnS4ktFxDNvXOLMPEdnsEkxO7XHiRR9y+kzDXc9Vi7ZizisZ -n8wUu2AeXOBgSiinOXoNw7yXkl4COm633GyWNd3TJqQi332sVCsErvbRMolwUZss -mzhR9FMjmTvi+YrVkYfKmOw1uwMojd0hKGyUHwO61IqkqIDVq8Hkt5PpAoGBAMlH -RdwF7ToJhdeMjm7pr0oSSuWK/g/y9Ow3yMnpyuJrCe2248FUy61k0gswFjPi/3jD -I4MR7CJsHxNv5lX0fB5q9+P/CtGJdWjVA4GkTZ175I/4dcDk5bT+cBB/ftNFYqWq -Frux3Vw9kxpNrjOZY7RKEAhkJVfPEBHSo5+NODexAoGAXohoO9jOeLtYFOYRdKxj -bbL7fwiR+ecBakiuakoIFc+ibH57fDvxA6YkbLFOVNrpsTVNIbgO9Jois3GhrEGH -8TbGfohpmwC7nZ62aFJSNxD48gYvYzMamo0WymM1uH3jwlJY/kVO6KHopcN8+kQS -/zG8+V/OgnBBvyfWWX8ygio= ------END PRIVATE KEY----- diff --git a/content/examples/nginx/_wildcard.localhost.pomerium.io.pem b/content/examples/nginx/_wildcard.localhost.pomerium.io.pem deleted file mode 100644 index fc28599ff..000000000 --- a/content/examples/nginx/_wildcard.localhost.pomerium.io.pem +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEAjCCAmqgAwIBAgIRAJGdiQDsLfchZYUtx06mQpswDQYJKoZIhvcNAQELBQAw -RTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMQ0wCwYDVQQLEwR0ZXN0 -MRQwEgYDVQQDEwtta2NlcnQgdGVzdDAeFw0xOTA2MDEwMDAwMDBaFw0zMDA4MjQx -OTQyNTBaMDgxJzAlBgNVBAoTHm1rY2VydCBkZXZlbG9wbWVudCBjZXJ0aWZpY2F0 -ZTENMAsGA1UECxMEdGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -ANd95OZ42ZAUresKstx2H2lWuxKNs04A/YEhDcB8Z1/9LRSqNTVSFc5vaAubkOyP -+8W+z99KSJqEF2PvNHV2HuN06d/dCBwCMgxOjuwmCCwAEcEXS8dUxcm02haZn4Bg -6KuyfbY3cShQ2ZeOWvX0udbTsO2QckU9ixgXLTW44QoZvMpCHwToMW/e082n+tpQ -eQZIBSlPXW1lx1+9tIe5I3jHMY6zpP1AKe7TAIZvYwk1ryXl2G1W7Ln2NxlYzaLg -QEudexhseGSD+5nGdV+bdjGA0zxsDZPUOpJTGOku3sO3L0wcFoTIdWsf+ddiW4XX -AjuM0LYDt0TpUqoCRKYUobsCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgWgMBMGA1Ud -JQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwHwYDVR0jBBgwFoAU0t8UaNj7 -xry1h0qnTAm8Sxv69aMwIgYDVR0RBBswGYIXKi5sb2NhbGhvc3QucG9tZXJpdW0u -aW8wDQYJKoZIhvcNAQELBQADggGBAJhOdplKGoR7/83qDjELdjhaoecZASqs5M+P -Sxm7z5s+KSbElebw6/rHJciKAlT9tqHQO6CqliQ9hl4AHWxi+cjpwfxyqWn/VGIa -4WoGyInd/I2PDne+5bIj0MXkikilk5NsJtypvGGjZJTF2T07QfXLlLi3nYTMHYzt -TLZpu7vK+B2ZGCGG4o9pws5ZFjtuOXEDGsE1APPp3xjvC/uJt2xgqo4XcRGIVHgm -mY2yi5KmUCAv0HHdDjxZoqEDazv8t/VuPc3hJcuUcIBZvyMFyPNMqN5ePI7D5TkD -zOqW28I8jpB5zdDpCr4qXsU+Cf+4fB0jDncBq95n1v8EJsm7zeTIFZNgLv3ISthF -lGEFS1zv+ybCOYPl3H0yd13S6N4QUHbESXHvZ2l2V1qDiKrfFcVhQ5ZEDD7/HDqT -N+v7zzMOzmPNCSiky1lMMj/vP87AjaliJnvBcT4F5iU867ws/Refh+yege2l6roO -LEM1YmdMYuNFbCsS2BbQsK9mbDkcmQ== ------END CERTIFICATE----- diff --git a/content/examples/nginx/config.yaml.md b/content/examples/nginx/config.yaml.md deleted file mode 100644 index 561dc62a5..000000000 --- a/content/examples/nginx/config.yaml.md +++ /dev/null @@ -1,22 +0,0 @@ -```yaml title="config.yaml" -# Main configuration flags : https://www.pomerium.com/docs/reference/ -address: :80 -cookie_secret: YVFTMIfW8yBJw+a6sYwdW8rHbU+IAAV/SUkCTg9Jtpo= -shared_secret: 80ldlrU2d7w+wVpKNfevk6fmb8otEx6CqOfshj2LwhQ= - -idp_provider: "google" -idp_client_id: REPLACE_ME -idp_client_secret: REPLACE_ME - -insecure_server: true -forward_auth_url: http://fwdauth.localhost.pomerium.io -authenticate_service_url: https://authenticate.localhost.pomerium.io - -policy: - - from: https://verify.localhost.pomerium.io - to: https://httpbin - allowed_domains: - - pomerium.com - - gmail.com - pass_identity_headers: true -``` diff --git a/content/examples/nginx/docker-compose.yaml.md b/content/examples/nginx/docker-compose.yaml.md deleted file mode 100644 index 5e3e7b3de..000000000 --- a/content/examples/nginx/docker-compose.yaml.md +++ /dev/null @@ -1,30 +0,0 @@ -```yaml title="docker-compose.yaml" -services: - nginx: - # to emulate nginx-ingress behavior, use openresty which comes with 'escaped_request_uri' - # pre-compiled. Also uncomment lines marked `uncomment to emulate nginx-ingress behavior` - # in the nginx `.conf` configuration files. - # image: openresty/openresty - image: nginx - restart: unless-stopped - ports: - - "80:80" - - "443:443" - volumes: - - ./verify.conf:/etc/nginx/conf.d/verify.conf - - ./pomerium.conf:/etc/nginx/conf.d/pomerium.conf - - ./_wildcard.localhost.pomerium.io.pem:/etc/nginx/nginx.pem - - ./_wildcard.localhost.pomerium.io-key.pem:/etc/nginx/nginx-key.pem - - ./proxy.conf:/etc/nginx/proxy.conf - - verify: - image: pomerium/verify:latest - expose: - - 80 - pomerium: - image: pomerium/pomerium:latest - volumes: - - ./config.yaml:/pomerium/config.yaml:ro - expose: - - 80 -``` diff --git a/content/examples/nginx/pomerium.conf.md b/content/examples/nginx/pomerium.conf.md deleted file mode 100644 index dd80d025b..000000000 --- a/content/examples/nginx/pomerium.conf.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -# cSpell:ignore fwdauth ---- -```nginx -# Pomerium endpoint -server { - listen 443 ssl; - server_name authenticate.localhost.pomerium.io fwdauth.localhost.pomerium.io; - ssl_certificate /etc/nginx/nginx.pem; - ssl_certificate_key /etc/nginx/nginx-key.pem; - - location / { - proxy_pass http://pomerium; - include /etc/nginx/proxy.conf; - } -} - -# Define an upstream so that we don't need resolvers when we use variables in proxy_pass directives -# https://stackoverflow.com/questions/17685674/nginx-proxy-pass-with-remote-addr -upstream pomerium { - server pomerium; -} -``` diff --git a/content/examples/nginx/proxy.conf b/content/examples/nginx/proxy.conf deleted file mode 100644 index d49ccae92..000000000 --- a/content/examples/nginx/proxy.conf +++ /dev/null @@ -1,64 +0,0 @@ -set $pass_access_scheme $scheme; - -set $pass_server_port $server_port; - -set $best_http_host $http_host; -set $pass_port $pass_server_port; - -set $proxy_alternative_upstream_name ""; - -client_max_body_size 1m; - - -proxy_set_header Host $best_http_host; - -# Pass the extracted client certificate to the backend - -# Allow websocket connections -proxy_set_header Upgrade $http_upgrade; - -proxy_set_header Connection ""; - -# uncomment to emulate nginx-ingress -# set_escape_uri $escaped_request_uri $request_uri; - -# proxy_set_header X-Request-ID $req_id; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $remote_addr; -proxy_set_header X-Forwarded-Host $best_http_host; -proxy_set_header X-Forwarded-Port $pass_port; -proxy_set_header X-Forwarded-Proto $pass_access_scheme; - -proxy_set_header X-Scheme $pass_access_scheme; - -# Pass the original X-Forwarded-For -proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for; - -# mitigate HTTPoxy Vulnerability -# https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/ -proxy_set_header Proxy ""; - -# Custom headers to proxied server - -proxy_connect_timeout 5s; -proxy_send_timeout 60s; -proxy_read_timeout 60s; - -proxy_buffering off; -proxy_buffer_size 4k; -proxy_buffers 4 4k; - -proxy_max_temp_file_size 1024m; - -proxy_request_buffering on; -proxy_http_version 1.1; - -proxy_cookie_domain off; -proxy_cookie_path off; - -# In case of errors try the next upstream server before returning an error -proxy_next_upstream error timeout; -proxy_next_upstream_timeout 0; -proxy_next_upstream_tries 3; - -proxy_redirect off; diff --git a/content/examples/nginx/rootCA-key.pem b/content/examples/nginx/rootCA-key.pem deleted file mode 100644 index 1b5ac7f1e..000000000 --- a/content/examples/nginx/rootCA-key.pem +++ /dev/null @@ -1,40 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQCub8x6MRI1aWZV -k7qfpQn7CK6fCHNceBhSQFMHBJXQLEAe34uNgF1h+NQGM2zaKDZ8hIsRNZq0dV/g -Xyd7AMA5C8DyyHfqzoiHJeTXKoqGEmi/MyXfnHr6N4rQpoG97SbACKYfNOh/MD05 -gIg51LrbTK1GzFyg0AVntsvmm3r3NNHv/BJKVKV+2HZx1D83xcBstdLDAPdtmU3z -STzixQYDTlzs1gUrJPfJAi1sAMM/RbDKTmgsYJopxADRYldOIvZEZqPrupInUi4v -iFEosb0dpSSeHkKBgVl81X2ro+WH4vgfoeGkpu6mh67FfN1WljMf63E6yOEBcqxE -+Vc9O+ysruODnma1d+DfXoHoZInUhzUM7nTdbsftmb0C5bFA3ts16WGZ1g21Hi7m -NH2MdW2hLyRngAU9AHTWObdBxb4MBmBSF5ZIElcsfLABilHG508L2ZYM+uqOb0iW -AMcVyrli7EaDEOF/oUv7WsDAekwGKKfy9exfWhw7+yn+UYG4oPUCAwEAAQKCAYAx -e5d2xjrTGf4koo6bQPcO1kyq4nvPLGZB1ut2ny9caWEbIPD2iAZ1h1+mDqp/TE8A -jZzhmeIz9OPowzVw6CqfRB1NAd86pbIHHJHJE9FN7ST3sCu7PimIl37yZ3mAhiiq -6wks6xZVFjsX98UtGpKTKTIyVkCkgb42yJ0Y4txECiDPwiLyIQb9b6xR6BKy4I8Q -h5etJ7YIyidZr1ntPlTRVUZ5DNFUht0fkVWPQLwiU8Ot8AYPKKwy0t4kh5Aao0Hf -CDQP6Y5/XXKLl5bNi/SO5eg6jk3DnILwPkjXM3tVxcag+KmMc4GfVmVVDP+QkmVl -LtGOHuBeyicdC5/jt6xMwbsEdY/YFjlO4WDH/5e8F7KG1X3OjTmqwdNjSNg4rXni -u0ZEG+/o80ha21lCys+QpQ9PQmYPaGlzVPY9z0F6JsAlXNbNRIIOsJNEKlAICWXF -9YyAaD8pV60UhK67q5wZ3uxyAjplM5+930asL5MPgb4BEvRY4bWlOe55lySXsbUC -gcEA0HnqdCQBfmiylZv4Uh8JVojSZcZFtFU8V02TY/XrWjwzWv8z1ZXnzx18kAz7 -islThqlvr38HXwFfUNDhI/IIp+8zcvT9T56e1T8jYxhcaTZBEZ7XlG/jWbWbRx/k -JEctixh7J5EhbsxhC7TfuH9lQ2r50WvmmrGpLoqHDe5fyKFTpbUkrGB19idiw9oI -awjxOgN+uRrTFjuOPhxgfSwJGwPnE0my8lS/5fPvNUuQdWecqEe3CTFjVXY44IzB -7W9HAoHBANYzbsNClt8HgLyp0XZg4W19BuCic6qJZhOSVoUlGFTTa2dTQnSfq5NL -O1GCfZ/fy0QZvvBebf+Mf3WycEv/BbxRT0lDP0QjdamHkn9mGK+ODmYxvPu7Lqk9 -5acrXM8uXuK4bkT2eXKE2H7x9jrnxpSI/zE3cwic+GlQWH85ywAKwT07g3BiM5GJ -pHpoJGwxraBUDb6HPTgTsVzPtvCbKqYw9uUalPDGI1Pc0iEitT5s41HT57P10hnD -gOkIyOXj4wKBwEBQfC3cNcHDluRku5TKEl1p1E6lfjeF3Bmqyv+ZjEPIMqet91W6 -60qP9C+Ucb19IpF2kAf6DlIW4ErURcCLGHSGbL7YKZV4f9OVqNsXVtr2a9h9wk/+ -vIqeZgrpIb63Xqt8n/Gy6jd+QaoU4LfQRXMo+2zJ9theWq0K+2Mm2NHSQzXpziiH -kZygxe1ZxCMRHSoijeOZDOnc8aLjqjizbxOwfocKw3PTBWhxeqhcaXJuxnt7tFHX -tKdW03Eiu2j+XQKBwQCdyCcX1+4wfWNcFa9Aht6m+wjc4W1YOnuhgRMQYqHIoi+k -XdU++Pq2th0MzpVg9cXR9TEL+FMIgeLFvNoxcLo13KMNsWZh98jNRxsnkvouHvMG -Xi76MwiNDBYljLCBwIOOeBJp5DDTpX2gDPW2sFI7yapJA7JNrurhEJkPpm+dKU7s -nvEUEJIx63Tn4dyqgfGGf0Pci9wReZgVaMA1/eZtovXLD0iVDy6osKlsVRey0xyj -gvdTPYk1Byjm/1yU0scCgcEAgCzLcqc7O1t9kXNo48Lh+O3wtxYVZ0FTHAz0TtcR -oVaRaok3aSEkCuZlBf4a9CJCKxzkDPg7dNNcUt5ng16XxJoEcIgf8FeS+BZS9L0O -bLOQoAggW41OlRnX9yQIti9w/MR+qRzKSftTZcP8ySls4SCphlqsx/a7JXncgwI8 -QmML5MzfffKdB1RNs5yVWyzSsxHgmVGLcA9UziomcUPCrpXp10C/yzGnMPAyAwlo -9k5AET80ZLKc7XYQ0NxI2yCf ------END PRIVATE KEY----- diff --git a/content/examples/nginx/rootCA.pem b/content/examples/nginx/rootCA.pem deleted file mode 100644 index 9ab4190ab..000000000 --- a/content/examples/nginx/rootCA.pem +++ /dev/null @@ -1,26 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEWTCCAsGgAwIBAgIQBA3zYaPnHKhRmKC37lWvEjANBgkqhkiG9w0BAQsFADBF -MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExDTALBgNVBAsTBHRlc3Qx -FDASBgNVBAMTC21rY2VydCB0ZXN0MB4XDTIwMDgyNDE5NDIwOVoXDTMwMDgyNDE5 -NDIwOVowRTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMQ0wCwYDVQQL -EwR0ZXN0MRQwEgYDVQQDEwtta2NlcnQgdGVzdDCCAaIwDQYJKoZIhvcNAQEBBQAD -ggGPADCCAYoCggGBAK5vzHoxEjVpZlWTup+lCfsIrp8Ic1x4GFJAUwcEldAsQB7f -i42AXWH41AYzbNooNnyEixE1mrR1X+BfJ3sAwDkLwPLId+rOiIcl5NcqioYSaL8z -Jd+cevo3itCmgb3tJsAIph806H8wPTmAiDnUuttMrUbMXKDQBWe2y+abevc00e/8 -EkpUpX7YdnHUPzfFwGy10sMA922ZTfNJPOLFBgNOXOzWBSsk98kCLWwAwz9FsMpO -aCxgminEANFiV04i9kRmo+u6kidSLi+IUSixvR2lJJ4eQoGBWXzVfauj5Yfi+B+h -4aSm7qaHrsV83VaWMx/rcTrI4QFyrET5Vz077Kyu44OeZrV34N9egehkidSHNQzu -dN1ux+2ZvQLlsUDe2zXpYZnWDbUeLuY0fYx1baEvJGeABT0AdNY5t0HFvgwGYFIX -lkgSVyx8sAGKUcbnTwvZlgz66o5vSJYAxxXKuWLsRoMQ4X+hS/tawMB6TAYop/L1 -7F9aHDv7Kf5Rgbig9QIDAQABo0UwQzAOBgNVHQ8BAf8EBAMCAgQwEgYDVR0TAQH/ -BAgwBgEB/wIBADAdBgNVHQ4EFgQU0t8UaNj7xry1h0qnTAm8Sxv69aMwDQYJKoZI -hvcNAQELBQADggGBAFZT6Zdg+tt+8t6Bo9Boe8uOKnqrCSuOCyMIajDLgijPRlHf -iJRggRjGT2Ig7c0nzL5SfeuExoMPMUmkfNAKki3VhK7cxLijDtn4fOmyyW5OO7AT -zwSmOyakHXq4ip3klysNGVPzxjwHBuK5rCdPa2X1WXN4PeM6NQvGZB34hQ1962om -1gad4YardZ81fVLJfOlCtIPD87TSreVGxiawUIAAGWgDuVMouN4PvqTUyEmorgxi -hSaiVDCSlS/nuW5fuOGzZ1Ko9UhbCsmO3bbLzXKcjuwKeyzgyjozHMyx5gUhhOFk -kqDIuIven3j+uLke0WAK++Z11vM8fVn0wB80RqubuTbqJzvH3w0R/PWVd0yAMFNu -Y2Z+AZ0OwMm9BtqfwoW5PZSIMF06q6IbLmuLEH/5dE9xDN0s5Ia8gn7ySYqso+62 -yJjURRgGJeXLkrjfeSav39D0bg+JCB7J63Z7BCz6/Jv1TL45yWbeMmtqFPH6nS5t -25uIk/1regWTCajVMg== ------END CERTIFICATE----- diff --git a/content/examples/nginx/verify.conf.md b/content/examples/nginx/verify.conf.md deleted file mode 100644 index 178162789..000000000 --- a/content/examples/nginx/verify.conf.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -# cSpell:ignore fwdauth authredirect ---- -```nginx -# Protected application -server { - listen 80; - listen 443 ssl http2; - - server_name verify.localhost.pomerium.io; - ssl_certificate /etc/nginx/nginx.pem; - ssl_certificate_key /etc/nginx/nginx-key.pem; - - - location = /ext_authz { - internal; - - proxy_pass_request_body off; - proxy_set_header Content-Length ""; - proxy_set_header X-Forwarded-Proto ""; - - proxy_set_header Host fwdauth.localhost.pomerium.io; - proxy_set_header X-Original-URL $scheme://$http_host$request_uri; - proxy_set_header X-Original-Method $request_method; - proxy_set_header X-Real-IP $remote_addr; - - proxy_set_header X-Forwarded-For $remote_addr; - - proxy_set_header X-Auth-Request-Redirect $request_uri; - - proxy_buffering off; - - proxy_buffer_size 4k; - proxy_buffers 4 4k; - proxy_request_buffering on; - proxy_http_version 1.1; - - proxy_ssl_server_name on; - proxy_pass_request_headers on; - - client_max_body_size 1m; - - # Pass the extracted client certificate to the auth provider - - set $target http://pomerium/verify?uri=$scheme://$http_host$request_uri; - - # uncomment to emulate nginx-ingress behavior - # set $target http://pomerium/verify?uri=$scheme://$http_host$request_uri&rd=$pass_access_scheme://$http_host$escaped_request_uri; - proxy_pass $target; - } - - location @authredirect { - internal; - add_header Set-Cookie $auth_cookie; - - # uncomment to emulate nginx-ingress behavior - # return 302 https://fwdauth.localhost.pomerium.io/?uri=$scheme://$host$request_uri&rd=$pass_access_scheme://$http_host$escaped_request_uri; - - return 302 - https://fwdauth.localhost.pomerium.io/?uri=$scheme://$host$request_uri; - } - - location / { - proxy_pass http://verify; - - include /etc/nginx/proxy.conf; - # If we get a 401, respond with a named location - error_page 401 = @authredirect; - # this location requires authentication - auth_request /ext_authz; - auth_request_set $auth_cookie $upstream_http_set_cookie; - add_header Set-Cookie $auth_cookie; - } -} -``` diff --git a/content/examples/tiddlywiki/docker-compose.yaml.md b/content/examples/tiddlywiki/docker-compose.yaml.md deleted file mode 100644 index 4f21ed7bd..000000000 --- a/content/examples/tiddlywiki/docker-compose.yaml.md +++ /dev/null @@ -1,34 +0,0 @@ -```yaml title="docker-compose.yaml" -services: - pomerium: - image: pomerium/pomerium:latest - volumes: - # Use a volume to store ACME certificates - - ./config.yaml:/pomerium/config.yaml:ro - ports: - - 443:443 - - tiddlywiki_init: - image: elasticdog/tiddlywiki:latest - volumes: - - ./wiki:/tiddlywiki - command: ['mywiki', '--init', 'server'] - - tiddlywiki: - image: elasticdog/tiddlywiki:latest - ports: - - 8080:8080 - volumes: - - ./wiki:/tiddlywiki - command: - - mywiki - - --listen - - host=0.0.0.0 - - authenticated-user-header=x-pomerium-claim-email - - readers=reader@example.com - - writers=writer@example.com - - username= - - password=password - depends_on: - - tiddlywiki_init -``` diff --git a/content/examples/tooljet/config-console.yaml.md b/content/examples/tooljet/config-console.yaml.md index 6591d1e37..375236d7b 100644 --- a/content/examples/tooljet/config-console.yaml.md +++ b/content/examples/tooljet/config-console.yaml.md @@ -11,16 +11,16 @@ routes: to: http://verify:8000 pass_identity_headers: true policy: - - allows: - or: + - allow: + or: - email: - is: user@example.com + is: user@example.com - from: https://console.localhost.pomerium.io to: http://pomerium_console:8701 pass_identity_headers: true policy: - - allows: - or: + - allow: + or: - email: - is: user@example.com + is: user@example.com ``` diff --git a/content/examples/tooljet/console-compose.yaml.md b/content/examples/tooljet/console-compose.yaml.md index 61a6dab67..4be2d2843 100644 --- a/content/examples/tooljet/console-compose.yaml.md +++ b/content/examples/tooljet/console-compose.yaml.md @@ -26,7 +26,7 @@ services: condition: service_healthy pomerium: condition: service_started - image: docker.cloudsmith.io/pomerium/enterprise/pomerium-console:v0.21.0 + image: docker.cloudsmith.io/pomerium/enterprise/pomerium-console:v0.32.0 command: - 'serve' - '--config' @@ -49,7 +49,7 @@ services: database: networks: main: {} - image: postgres:latest + image: postgres:17 restart: always healthcheck: test: ['CMD-SHELL', 'pg_isready -d postgres -U postgres'] @@ -93,7 +93,7 @@ services: postgres: networks: main: {} - image: postgres:13 + image: postgres:17 restart: always ports: - 5433:5432 diff --git a/content/examples/tooljet/docker-compose.yaml.md b/content/examples/tooljet/docker-compose.yaml.md index 47c084979..daecfb820 100644 --- a/content/examples/tooljet/docker-compose.yaml.md +++ b/content/examples/tooljet/docker-compose.yaml.md @@ -41,7 +41,7 @@ services: postgres: networks: main: {} - image: postgres:13 + image: postgres:17 restart: always ports: - 5432:5432 diff --git a/content/examples/traefik-ingress/README.md b/content/examples/traefik-ingress/README.md deleted file mode 100644 index edffbcecf..000000000 --- a/content/examples/traefik-ingress/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Pomerium as forward-auth provider for Traefik on Kubernetes - -Run this demo locally on your kubernetes capable workstation or: - - use `kubectl port-forward service/traefik 80:80 443:443` - - replace `localhost.pomerium.io` with your own domain - -## Includes - -- Authentication and Authorization managed by pomerium -- Routing / reverse proxying handled by traefik -- Installation using upstream `helm` charts - -## How - -- Update `values/pomerium.yaml` for your e-mail address, if not using gmail/google. -- Replace IdP secrets in `values/pomerium.yaml`. -- Run `./add_repos.sh` from this directory. -- Run `./install.sh` from this directory. -- Navigate to `https://hello.localhost.pomerium.io` diff --git a/content/examples/traefik-ingress/add_repos.sh.md b/content/examples/traefik-ingress/add_repos.sh.md deleted file mode 100755 index 23b5c69e0..000000000 --- a/content/examples/traefik-ingress/add_repos.sh.md +++ /dev/null @@ -1,5 +0,0 @@ -```bash -helm repo add bitnami https://charts.bitnami.com/bitnami -helm repo add pomerium https://helm.pomerium.io -helm repo add traefik https://containous.github.io/traefik-helm-chart -``` diff --git a/content/examples/traefik-ingress/crds/middleware.yaml.md b/content/examples/traefik-ingress/crds/middleware.yaml.md deleted file mode 100644 index 2d55caa05..000000000 --- a/content/examples/traefik-ingress/crds/middleware.yaml.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -# cSpell:ignore containo ---- -```yaml -apiVersion: traefik.containo.us/v1alpha1 -kind: Middleware -metadata: - name: auth -spec: - forwardAuth: - address: https://pomerium-proxy.pomerium - tls: - insecureSkipVerify: true - trustForwardHeader: true -``` diff --git a/content/examples/traefik-ingress/install.sh.md b/content/examples/traefik-ingress/install.sh.md deleted file mode 100755 index 9d9784b2d..000000000 --- a/content/examples/traefik-ingress/install.sh.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -# cSpell:ignore crds ---- -```bash {4,10,16,22,25} -kubectl create namespace pomerium - -# Create shared TLS secret -kubectl create secret tls wildcard-tls \ - --namespace pomerium \ - --cert=_wildcard.localhost.pomerium.io.pem \ - --key=_wildcard.localhost.pomerium.io-key.pem - -# Install Traefik helm chart -helm upgrade --install --wait \ - --namespace pomerium \ - traefik traefik/traefik \ - --values values/traefik.yaml - -# Install Pomerium helm chart -helm upgrade --install --wait \ - --namespace pomerium \ - pomerium pomerium/pomerium \ - --values values/pomerium.yaml - -# Create middleware -kubectl --namespace pomerium apply -f crds/middleware.yaml - -# Install hello app -helm upgrade --install --wait \ - --namespace pomerium \ - --version 6.2.1 \ - hello bitnami/nginx \ - --values values/hello.yaml -``` diff --git a/content/examples/traefik-ingress/values/hello.yaml.md b/content/examples/traefik-ingress/values/hello.yaml.md deleted file mode 100644 index a7a8a2307..000000000 --- a/content/examples/traefik-ingress/values/hello.yaml.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -# cSpell:ignore middlewares kubernetescrd ---- -```yaml -ingress: - enabled: true - hosts: - - name: hello.localhost.pomerium.io - path: / - - annotations: - traefik.ingress.kubernetes.io/router.middlewares: pomerium-auth@kubernetescrd - traefik.ingress.kubernetes.io/router.tls: "true" - tls: - - hosts: - - hello.localhost.pomerium.io - secretName: wildcard-tls -service: - type: ClusterIP -``` diff --git a/content/examples/traefik-ingress/values/pomerium.yaml.md b/content/examples/traefik-ingress/values/pomerium.yaml.md deleted file mode 100644 index 10bf74a88..000000000 --- a/content/examples/traefik-ingress/values/pomerium.yaml.md +++ /dev/null @@ -1,29 +0,0 @@ -```yaml -authenticate: - idp: - provider: REPLACE_ME - url: REPLACE_ME - clientID: REPLACE_ME - clientSecret: REPLACE_ME - -config: - rootDomain: localhost.pomerium.io - sharedSecret: R0+XRoGVpcoi4PfB8tMlvnrS5XUasO+D1frAEdYcYjs= - cookieSecret: FLPCOQKigK5EQnyXlBhchl5fgzNKqi3ubtvOGt477Dg= - generateTLS: true - routes: - - from: https://hello.localhost.pomerium.io - to: http://hello-nginx - policy: - - allow: - or: - - domain: - is: gmail.com -ingress: - annotations: - traefik.ingress.kubernetes.io/router.tls: "true" - secretName: wildcard-tls -forwardAuth: - enabled: true - internal: true -``` diff --git a/content/examples/traefik-ingress/values/traefik.yaml.md b/content/examples/traefik-ingress/values/traefik.yaml.md deleted file mode 100644 index b3a64685d..000000000 --- a/content/examples/traefik-ingress/values/traefik.yaml.md +++ /dev/null @@ -1,5 +0,0 @@ -```yaml -additionalArguments: - - "--serverstransport.insecureskipverify=true" - - "--entryPoints.websecure.forwardedHeaders.insecure" -```