Andrew Farries 503ef163f4 Stop setting X-Real-IP on upstream requests
The value of the header was set to the IP address of a machine inside
GCP rather than the the actual client IP address.

To ensure that the header contains the actual client IP address, this
header is now set at the GCP load balancer.
2023-01-16 21:50:24 +01:00

416 lines
10 KiB
Caddyfile

{
# disable automatic SSL certificate generation
auto_https off
# disable admin API server
# admin localhost:2019
admin off
# set default SNI for old clients
default_sni {$GITPOD_DOMAIN}
# debug
# configure plugin order
# https://caddyserver.com/docs/caddyfile/directives#directive-order
order gitpod.cors_origin before header
order gitpod.workspace_download before redir
order gitpod.headless_log_download before rewrite
order gitpod.configcat before rewrite
order gitpod.sec_websocket_key before header
servers {
protocols h1 h2 h2c
}
}
(compression) {
encode zstd gzip
}
# configure headers to force HTTPS and enable more strict rules for the browser
(security_headers) {
header {
# enable HSTS
Strict-Transport-Security max-age=31536000
# disable clients from sniffing the media type
X-Content-Type-Options nosniff
# Define valid parents that may embed a page
Content-Security-Policy "frame-ancestors 'self' https://*.{$GITPOD_DOMAIN} https://{$GITPOD_DOMAIN}"
# keep referrer data off of HTTP connections
Referrer-Policy no-referrer-when-downgrade
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-XSS-Protection "1; mode=block"
defer # delay changes
}
}
# workspace security headers
(workspace_security_headers) {
header {
# Disallow sharing the same browsing context when opened in a popup
Cross-Origin-Opener-Policy same-origin-allow-popups
}
import security_headers
}
(enable_log) {
log {
output stdout
format if "status > 399" jsonselect "{severity:level} {timestamp:ts} {logName:logger} {httpRequest>requestMethod:request>method} {httpRequest>protocol:request>proto} {httpRequest>status:status} {httpRequest>responseSize:size} {httpRequest>userAgent:request>headers>User-Agent>[0]} {httpRequest>requestUrl:request>uri} {httpRequest>requestHost:request>host} {cacheStatus:resp_headers>X-Cache-Status>[0]}" {
level_format "upper"
time_format "rfc3339_nano"
}
}
}
(enable_log_debug) {
log {
output stdout
format jsonselect "{severity:level} {timestamp:ts} {logName:logger} {httpRequest>requestMethod:request>method} {httpRequest>protocol:request>proto} {httpRequest>status:status} {httpRequest>responseSize:size} {httpRequest>userAgent:request>headers>User-Agent>[0]} {httpRequest>requestUrl:request>uri} {httpRequest>requestHost:request>host} {cacheStatus:resp_headers>X-Cache-Status>[0]}" {
level_format "upper"
time_format "rfc3339_nano"
}
}
}
(remove_server_header) {
header {
-server
-x-powered-by
}
}
(ssl_configuration) {
tls /etc/caddy/certificates/tls.crt /etc/caddy/certificates/tls.key {
protocols tls1.2
#ca_root <pem_file>
}
}
(upstream_connection) {
lb_try_duration 1s
}
(debug_headers) {
header X-Gitpod-Region {$GITPOD_REGION}.{$GITPOD_INSTALLATION_SHORTNAME}
}
(workspace_transport) {
transport http {
tls_insecure_skip_verify
keepalive 60s
keepalive_idle_conns 100
}
}
(google_storage_headers) {
header {
-x-guploader-uploadid
-etag
-x-goog-generation
-x-goog-metageneration
-x-goog-hash
-x-goog-stored-content-length
-x-gitpod-region
-x-goog-stored-content-encoding
-x-goog-storage-class
-x-goog-generation
-x-goog-metageneration
-cache-control
-expires
defer # delay changes
}
}
(slow_fast_matchers) {
@slow {
header X-Gitpod-Slow-Database "true"
}
@fast {
not header X-Gitpod-Slow-Database "true"
}
}
# Kubernetes health-check
:8003 {
respond /live 200
respond /ready 200
}
# TODO: refactor once we can listen only in localhost
:9545 {
metrics /metrics {
disable_openmetrics
}
}
# public-api
api.{$GITPOD_DOMAIN} {
log {
level DEBUG
output stdout
}
gitpod.cors_origin {
allowed_origins https://{$GITPOD_DOMAIN}
}
reverse_proxy public-api-server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9002
}
# always redirect to HTTPS
http:// {
redir https://{host}{uri} permanent
}
https://{$GITPOD_DOMAIN} {
import enable_log
import remove_server_header
import ssl_configuration
import security_headers
@proxy_public_api path /public-api*
handle @proxy_public_api {
uri strip_prefix /public-api
reverse_proxy public-api-server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9002
}
@workspace_download path /workspace-download*
handle @workspace_download {
import google_storage_headers
header {
# The browser needs to see the correct archive content type to trigger the download.
content-type "application/tar+gzip"
}
gitpod.workspace_download {
service http://server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000
}
# redirect works here because we "navigate" to this URL, which makes the browser handle this as primary request, and not fuff around with CORS at all
redir {http.gitpod.workspace_download_url} 303
}
@headless_log_download path /headless-log-download*
handle @headless_log_download {
header {
# Alltough logs are plain text "text/html" works for reliably for streaming
content-type "text/html; charset=utf-8"
}
# Perform lookup to server and actual reverse_proxy in one go because caddy's `reverse_proxy` is not powerful enough
gitpod.headless_log_download {
service http://server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000
}
}
@configcat path /configcat*
handle @configcat {
gitpod.cors_origin {
any_domain true
}
gitpod.configcat
}
@backend_wss {
path /api/gitpod /api/v1
}
handle @backend_wss {
gitpod.cors_origin {
base_domain {$GITPOD_DOMAIN}
}
gitpod.sec_websocket_key
forward_auth server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
uri /feature-flags/slow-database
header_up -Connection
header_up -Upgrade
copy_headers X-Gitpod-Slow-Database
}
import slow_fast_matchers
uri strip_prefix /api
reverse_proxy @fast server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
}
reverse_proxy @slow slow-server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
}
}
@backend path /api/* /headless-logs/*
handle @backend {
gitpod.cors_origin {
base_domain {$GITPOD_DOMAIN}
}
forward_auth server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
uri /feature-flags/slow-database
copy_headers X-Gitpod-Slow-Database
}
import slow_fast_matchers
uri strip_prefix /api
reverse_proxy @fast server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
# required for smooth streaming of terminal logs
flush_interval -1
}
reverse_proxy @slow slow-server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
# required for smooth streaming of terminal logs
flush_interval -1
}
}
@iam path /iam/*
handle @iam {
gitpod.cors_origin {
any_domain true
}
uri strip_prefix /iam
reverse_proxy iam.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9002 {
import upstream_connection
}
}
@codesync path /code-sync*
handle @codesync {
gitpod.cors_origin {
any_domain true
}
import compression
reverse_proxy server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
flush_interval -1
}
}
@local_app {
path /static/bin/gitpod-local-companion-*
}
handle @local_app {
import compression
reverse_proxy ide-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:80 {
import upstream_connection
}
}
@to_server path /auth/github/callback /auth /auth/* /apps /apps/*
handle @to_server {
import compression
forward_auth server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
uri /feature-flags/slow-database
copy_headers X-Gitpod-Slow-Database
}
import slow_fast_matchers
reverse_proxy @fast server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
}
reverse_proxy @slow slow-server.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3000 {
import upstream_connection
}
}
handle {
reverse_proxy dashboard.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:3001 {
import upstream_connection
}
}
@legacy_urls path /github.com/* /gitlab.com/* /bitbucket.org/*
handle @legacy_urls {
redir https://{$GITPOD_DOMAIN}/#{uri} permanent
}
handle_errors {
redir https://{$GITPOD_DOMAIN}/sorry/#Error%20{http.reverse_proxy.status_text} 302
}
}
# workspaces
https://*.*.{$GITPOD_DOMAIN} {
import enable_log
import workspace_security_headers
import remove_server_header
import ssl_configuration
import debug_headers
# foreign content route used by vscode to serve webview and webworker resources of the form
# https://{{hash_base_32}}.<cluster>.<gitpod_domain> or https://v--{{hash_base_32}}.<cluster>.<gitpod_domain>
# e.g:
# https://0d9rkrj560blqb5s07q431ru9mhg19k1k4bqgd1dbprtgmt7vuhk.ws-us34xl.gitpod.io (for webviews)
# https://v--0d9rkrj560blqb5s07q431ru9mhg19k1k4bqgd1dbprtgmt7vuhk.ws-us34xl.gitpod.io (for webworker)
@foreign_content2 header_regexp host Host ^(?:v--)?[0-9a-v]+.ws(-[a-z0-9]+)?.{$GITPOD_DOMAIN}
handle @foreign_content2 {
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
import workspace_transport
header_up X-WSProxy-Host {http.request.host}
}
}
@workspace_port header_regexp host Host ^(?P<workspacePort>[0-9]{2,5})-(?P<workspaceID>[a-z0-9][0-9a-z\-]+).ws(?P<location>-[a-z0-9]+)?.{$GITPOD_DOMAIN}
handle @workspace_port {
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
import workspace_transport
header_up X-Gitpod-WorkspaceId {re.host.workspaceID}
header_up X-Gitpod-Port {re.host.workspacePort}
header_up X-WSProxy-Host {http.request.host}
}
}
# experimental debug workspace route
@debug_workspace header_regexp host Host ^debug-(?P<workspaceID>[a-z0-9][0-9a-z\-]+).ws(?P<location>-[a-z0-9]+)?.{$GITPOD_DOMAIN}
handle @debug_workspace {
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
import workspace_transport
header_up X-Gitpod-WorkspaceId {re.host.workspaceID}
header_up X-WSProxy-Host {http.request.host}
}
}
@workspace header_regexp host Host ^(?P<workspaceID>[a-z0-9][0-9a-z\-]+).ws(?P<location>-[a-z0-9]+)?.{$GITPOD_DOMAIN}
handle @workspace {
reverse_proxy https://ws-proxy.{$KUBE_NAMESPACE}.{$KUBE_DOMAIN}:9090 {
import workspace_transport
header_up X-Gitpod-WorkspaceId {re.host.workspaceID}
header_up X-WSProxy-Host {http.request.host}
}
}
respond "Not found" 404
}
import /etc/caddy/vhosts/vhost.*