-
Notifications
You must be signed in to change notification settings - Fork 86
HTTP 301 redirect loop with Istio httpsRedirect feature enabled #1852
Description
Describe the bug
Istio supports TLS within Ingress Gateways. One feature of this support is an optional automatic redirect from HTTP to HTTPS. However, this feature appears incompatible with OrbStack's integration with ingress controllers, as enabling causes an infinite 301 redirect cycle on OrbStack but works in other Kubernetes environments.
To Reproduce
- Create a fresh Kubernetes cluster in OrbStack
- Install Istio per the OrbStack instructions
$ istioctl install --set values.cni.cniBinDir=/var/lib/rancher/k3s/data/current/bin/ --set values.cni.cniConfDir=/var/lib/rancher/k3s/agent/etc/cni/net.d
- Enable automatic side-car injection in the default namespace
$ kubectl label namespace default istio-injection=enabled --overwrite
- Deploy an example application with TLS and httpsRedirect enabled
$ cat <<EOF | kubectl apply -f -
---
apiVersion: v1
kind: Secret
metadata:
name: httpbin-credential
namespace: istio-system
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREF0TVJVd0V3WURWUVFLREF4bGVHRnQKY0d4bElFbHVZeTR4RkRBU0JnTlZCQU1NQzJWNFlXMXdiR1V1WTI5dE1CNFhEVEkxTURNeU16RXlNek16T1ZvWApEVEkyTURNeU16RXlNek16T1Zvd1B6RWVNQndHQTFVRUF3d1ZhSFIwY0dKcGJpNXJPSE11YjNKaUxteHZZMkZzCk1SMHdHd1lEVlFRS0RCUm9kSFJ3WW1sdUlHOXlaMkZ1YVhwaGRHbHZiakNDQVNJd0RRWUpLb1pJaHZjTkFRRUIKQlFBRGdnRVBBRENDQVFvQ2dnRUJBSklpUGdtbUk1cXc4ZVBqMUkxait2NjF0QjEwVi8wTnZ3UjRKRlNTSGhPTgpOTTZXVTJCQjY0UlBqdUFoV1ZCdlVyMXE0QkVGSFFLZnNzVHlvMFN0SkErUDEwM0JjTEs4Z1pmQnMyNTlMQ1JFCldFQStrK1h3VjBTZko1eEFHZUZ3ckJFeUJtT0p1aStjQWxDUXhtNm5YRk1rTzBmeUtKZ25qTW1hajlQOUNMSlUKMFQ4ODFhYzZWL2p3NFdaeVR1QTdjeFczc2NOVUFBQjNDakhPWWRVeTZBelVOUmc5UEFHSm1pUkxLa0JKc25XTApzSW5lNnBBT0liK1FvaUcyUXV6djl6cnBCMTdMc2xRbXFrNHpUM2dqQlVpUEkzMGNJODM0YnFmTEZRaUt2SENmCnlpUzZCMFRyM1M1cldhdlpRajdLTWVmSGxUT05MdlFiTFlBUjRmY0loRE1DQXdFQUFhTkNNRUF3SFFZRFZSME8KQkJZRUZCZm8wakNwOXl0TWQ0WkUvb1BxdkxpUGNtR2tNQjhHQTFVZEl3UVlNQmFBRkZPT1JTU05La1hLdHB2TgpsK1VNOGMxZFNmRFNNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUE5anNxSzBSUHlTQWtCYXJkVWhZM1JibENkCkNqTVNPVGlKamxEUTF4K2JSUHBRRDFwYWptQXA4SVZDT1l1QWltRFVLTDdxR2xKOVZwS1FLWW81VWFEWTFxRTYKeGxGMzNjUTY5Vm81bWxqMHp5Wi9rLzJOcUozMy80OEpzZlFjZWM3REZsczNTbEhpMEtUV0d1VnRKMHhlbUpWSwpYdWkvVEVkazJEYm5waDdGZjViZWFIdlNqV3h6M1lPK3E0dDdoTzAyTklDb3ZCZ1ZFdFpXTmRRS1ozUjhVUjluCjRSZWNQbXdKYmdoQThlMElCc2NhN1FabHl0TlRCYXpMUlpPZ0Q4YTBBeERNNE11ZEtPbGo3djRBVXcvbzVITDQKa0F4K2krT1NCNDVsSmxkU3RQRnJCbGY3MDVsL0NvNUpBZWZvYkdydkFWcDdqYTNSQjlJbnZzaUZiVlNuCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2Z0lCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktnd2dnU2tBZ0VBQW9JQkFRQ1NJajRKcGlPYXNQSGoKNDlTTlkvcit0YlFkZEZmOURiOEVlQ1JVa2g0VGpUVE9sbE5nUWV1RVQ0N2dJVmxRYjFLOWF1QVJCUjBDbjdMRQo4cU5FclNRUGo5ZE53WEN5dklHWHdiTnVmU3drUkZoQVBwUGw4RmRFbnllY1FCbmhjS3dSTWdaamlib3ZuQUpRCmtNWnVwMXhUSkR0SDhpaVlKNHpKbW8vVC9RaXlWTkUvUE5Xbk9sZjQ4T0ZtY2s3Z08zTVZ0N0hEVkFBQWR3b3gKem1IVk11Z00xRFVZUFR3Qmlab2tTeXBBU2JKMWk3Q0ozdXFRRGlHL2tLSWh0a0xzNy9jNjZRZGV5N0pVSnFwTwpNMDk0SXdWSWp5TjlIQ1BOK0c2bnl4VUlpcnh3bjhva3VnZEU2OTB1YTFtcjJVSSt5akhueDVVempTNzBHeTJBCkVlSDNDSVF6QWdNQkFBRUNnZ0VBSm9Bc0RSbS9CcW40eU54RkswMDhteS9mT09WbXF5NmNkWDU3ditaUlUwQmcKT2MrRVB2ZVBKK2hZRWJmbmtwZ0oyZ3JXNXRVTWpCenNHaFI5TElKYlhsZzgxdWtRbXA2c25BRjJGeldXVkNYSApoSUdZTUx3T0dlKytuVjJNRkFlOTViZmkxQVc4em45UllzMko0aXhvMkNUVEU0VDY2Zjk5aWI0Vmg3b0NPUTFXCm5RNTFiZnZxaDZaNjRiRWh0aWFKOFRobHF1Q1RuM0ROckxveGNMbTFlaURaeHJXMVlKTkx4VnRTa2VzbUV3WjYKNTUzSm96SWN4eGVTWkdPOHVNaUx5eHl2RkoydktONWNxbmZOdEx1SGVzZ2wveWFMZDY5eit4WU4rM2xuN0JtegpRUWNrNXVmcXFFaXJpekFud1hHaEFCVzA0LzVBWE1aSnpZaC9icVNKSFFLQmdRREs0eGJ0ZEdCRE4wRlhQUUtoCkFYTXVpRVFHN0U4NnltY1FxYlpZdzZmcGMyT1BGdUpyVUtxd1hqZHRRd2N1MjRILzl2VFJIV1o2NDNEYXdlVDIKdFVvOVZCV283SG42Q3B4dGZBL0RhalJmdVZpMUFvRHhCNXZIZ3FXUmJqSlZpb3YrNlM4NlFSZWNoTnJOVU1RYwphRmdWSmZxckhOR3BrTHNjeTcvRXo4Zm9SUUtCZ1FDNFk3VmVFY0VWWktSNmpmV0Mxd0NNSTFIR250cEZQb2xxCmdpRFRNckZMcDVKNENQOTd1VmxRbGNzbU4xRVdxWVFMcmtCZ3U4S1pZeFZxVnRhWXROb3lGdXBZMUkvNnI3N1YKYm5ZZ3BzWW8rOEU1aVc2WlNkK05mcTdBN0tuRGFsV2FYbXBXNkRtY3dPbFBIaEdyL2l5L2M0c3NyYmp4Z21IbgpEMGE0WmdGdUZ3S0JnUUNpbDdVakhSV2NLR2NENjgvMGlmM3R0NlNVeThKL0FmL3cyYUZacDRza1NxWHA0VlFZCjNxKzc0ZldYYVpVVEZ6VXFsWllERkFXeHpCNEFJazFFN1dxT2xaazZKREZva2lKa2wzem1oWEZ0bVZNZTFOL1MKeWQ4czEyV3FrOTVnc1VTYVIvUGlRcElTakdIeEVwM25pak8wMXhmNUU0SnUycDhwWjV2S3RSMm01UUtCZ1FDaApkd2JDS2svbldPdERPbjZNSlpRZ0kybWZ3VWtucTd5UG5RWDdpMzkvM1d6QVdqakc4aWJKRDNNR3N4ZjUvVlZaCkdTemN5RzUrL1NvcXBZSmoxTExoZS9tWThnSm1wbkU0MnZMc1lyNVI4eXRnSS8zS2s4c0VUN1BkMHlCUnRCTGsKQzl1WTRPQmFhUCtsUFpLQ0J5RE9RZkxVbkFmQXpNakltakwybExTWjN3S0JnQkxHalNPNFRBL2NxK3JnRTZhVApuQ1k1UWpLeXZBVXVsbmlrRUxWYy80aWRYWjlmLytVV0VMRm5scTlnbXFSUGptVTErc0NMWTdHK2xpa2xuZTQyCjV2MnRqT1Axd0JmZnpYL2VZVlhSQ3ZLSldRdkNkbERENk5aS2JpNGMvbTRyN3BmNm9zSmd5N2NyWWNMNGNZR2MKazRYOFFMKy84M1dTS3BWMG1IMHVraXpiCi0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0K
---
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
name: httpbin-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- httpbin.k8s.orb.local
tls:
httpsRedirect: true # sends 301 redirect for http requests
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: SIMPLE
credentialName: httpbin-credential # must be the same as secret
hosts:
- httpbin.k8s.orb.local
---
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin.k8s.orb.local
gateways:
- httpbin-gateway
http:
- route:
- destination:
host: httpbin
port:
number: 8000
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: httpbin
---
apiVersion: v1
kind: Service
metadata:
name: httpbin
labels:
app: httpbin
service: httpbin
spec:
ports:
- name: http
port: 8000
targetPort: 8080
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:
serviceAccountName: httpbin
containers:
- image: docker.io/mccutchen/go-httpbin:v2.15.0
imagePullPolicy: IfNotPresent
name: httpbin
ports:
- containerPort: 8080
EOF
- Try to access https://httpbin.k8s.orb.local and note that we get a 301 redirect even though we are already on HTTPS.
Expected behavior
Accessing http://httpbin.k8s.orb.local should redirect to https://httpbin.k8s.orb.local, and accessing https://httpbin.k8s.orb.local should serve the httpbin application.
Instead, both http and https return a 301 redirect to https://httpbin.k8s.orb.local/ (note the added trailing slash), resulting in an infinite redirect cycle.
Diagnostic report (REQUIRED)
OrbStack info:
Version: 1.10.3
Commit: 2b5dd5f580d80a3d2494b7b40dde2ef46813cfc5 (v1.10.3)
System info:
macOS: 15.3.2 (24D81)
CPU: arm64, 16 cores
CPU model: Apple M4 Max
Model: Mac16,5
Memory: 128 GiB
Full report: https://orbstack.dev/_admin/diag/orbstack-diagreport_2025-03-23T13-31-41.426135Z.zip
Screenshots and additional context (optional)
Removing
tls:
httpsRedirect: true # sends 301 redirect for http requests
allows the https endpoint to be reached as expected, though we now lack the http->https promotion redirect feature.