Skip to content

Commit 3339e41

Browse files
authored
docs(atlantis): document OIDC web UI authentication (#566)
Closes #346. Adds a README section covering two ways to put the Atlantis web UI behind an OIDC IdP: - OIDC at the ingress/load balancer (links the ALB IngressGroup example from #346). - An oauth2-proxy sidecar, portable across ingress controllers/clouds, run as a native sidecar (initContainers + restartPolicy: Always) and exposed via service.extraPorts, with webhooks kept off the auth path. Edits README.md.gotmpl and regenerates README.md via helm-docs. Patch chart version bump only. Signed-off-by: DrFaust92 <ilia.lazebnik@gmail.com>
1 parent 4afb61d commit 3339e41

3 files changed

Lines changed: 203 additions & 1 deletion

File tree

charts/atlantis/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ apiVersion: v1
33
appVersion: v0.45.0
44
description: A Helm chart for Atlantis https://www.runatlantis.io
55
name: atlantis
6-
version: 6.9.1
6+
version: 6.9.2
77
keywords:
88
- terraform
99
home: https://www.runatlantis.io

charts/atlantis/README.md

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,107 @@ extraManifests:
136136
137137
Optionally, set `service.internalTrafficPolicy: Local` or `Cluster` depending on your environment and how you want internal routing handled.
138138

139+
## Authenticating the Web UI with OIDC
140+
141+
Atlantis itself only ships HTTP Basic Auth (`basicAuth`) for the web UI. To put the UI behind an OIDC identity provider (Okta, Google, Entra ID, Keycloak, ...) you have two common options.
142+
143+
### Option 1: OIDC at the ingress / load balancer
144+
145+
If your ingress controller can perform OIDC itself, this is the least moving parts. For example, the AWS Load Balancer Controller can authenticate directly on the ALB via the `alb.ingress.kubernetes.io/auth-*` annotations. A full ALB IngressGroup example (one Ingress for the VCS webhooks, one for the OIDC-protected UI) is in [#346](https://github.com/runatlantis/helm-charts/issues/346).
146+
147+
### Option 2: An [oauth2-proxy](https://github.com/oauth2-proxy/oauth2-proxy) sidecar
148+
149+
This is portable across ingress controllers and clouds. The proxy runs alongside Atlantis, terminates the OIDC flow, and forwards authenticated requests to Atlantis on `localhost`.
150+
151+
The key thing to get right is that **VCS webhooks must not go through the auth proxy** — the webhook sender cannot complete an interactive login. So:
152+
153+
- Keep the default `service` port pointed at Atlantis (`targetPort: 4141`) and send webhooks there directly.
154+
- Add an extra service port that targets the proxy, and route only the browser-facing UI host/path to it.
155+
156+
Run the proxy as a native sidecar (`initContainers` with `restartPolicy: Always`, supported since the chart version that allows `restartPolicy` on containers) so it shares the Pod lifecycle, or as a plain `extraContainers` entry on older versions:
157+
158+
```yaml
159+
# Expose the proxy on a second service port; webhooks keep using the default port -> 4141.
160+
service:
161+
extraPorts:
162+
- name: atlantis-ui
163+
port: 8080
164+
protocol: TCP
165+
targetPort: oauth2-proxy
166+
167+
# Native sidecar (requires restartPolicy support). Use extraContainers instead on older charts.
168+
initContainers:
169+
- name: oauth2-proxy
170+
# renovate: image=oauth2-proxy/oauth2-proxy
171+
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3-alpine
172+
restartPolicy: Always
173+
args:
174+
- --config=/etc/oauth2-proxy/oauth2-proxy.cfg
175+
env:
176+
- name: OAUTH2_PROXY_CLIENT_ID
177+
valueFrom:
178+
secretKeyRef:
179+
name: atlantis-oidc
180+
key: client-id
181+
- name: OAUTH2_PROXY_CLIENT_SECRET
182+
valueFrom:
183+
secretKeyRef:
184+
name: atlantis-oidc
185+
key: client-secret
186+
# 32-byte cookie secret, e.g. `openssl rand -base64 32 | head -c 32 | base64`
187+
- name: OAUTH2_PROXY_COOKIE_SECRET
188+
valueFrom:
189+
secretKeyRef:
190+
name: atlantis-oidc
191+
key: cookie-secret
192+
ports:
193+
- name: oauth2-proxy
194+
containerPort: 4180
195+
protocol: TCP
196+
volumeMounts:
197+
- name: oauth2-proxy-config
198+
mountPath: /etc/oauth2-proxy
199+
securityContext:
200+
allowPrivilegeEscalation: false
201+
readOnlyRootFilesystem: true
202+
runAsNonRoot: true
203+
capabilities:
204+
drop: [ALL]
205+
206+
extraVolumes:
207+
- name: oauth2-proxy-config
208+
configMap:
209+
name: oauth2-proxy-config
210+
```
211+
212+
Provide the proxy config via your own ConfigMap (here through `extraManifests`). The example below targets Okta; swap `oidc_issuer_url` for your provider:
213+
214+
```yaml
215+
extraManifests:
216+
- apiVersion: v1
217+
kind: ConfigMap
218+
metadata:
219+
name: oauth2-proxy-config
220+
data:
221+
oauth2-proxy.cfg: |
222+
provider="oidc"
223+
oidc_issuer_url="https://<your-org>.okta.com"
224+
# Atlantis listens on the service targetPort (4141 by default).
225+
upstreams=["http://localhost:4141"]
226+
http_address=":4180"
227+
redirect_url="https://atlantis.example.com/oauth2/callback"
228+
email_domains="*"
229+
cookie_secure="true"
230+
reverse_proxy="true"
231+
skip_provider_button="true"
232+
code_challenge_method="S256"
233+
# Optionally restrict access to specific IdP groups:
234+
# oidc_groups_claim="groups"
235+
# allowed_groups=["atlantis-admins"]
236+
```
237+
238+
Then point the browser-facing Ingress host at the `atlantis-ui` service port (`8080`) while the webhook URL configured in your VCS continues to hit the default port. If you prefer a single port instead, route everything through the proxy and let webhooks bypass auth with `skip_auth_routes=["POST=^/events$"]`.
239+
139240
## Values
140241

141242
| Key | Type | Default | Description |

charts/atlantis/README.md.gotmpl

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,107 @@ extraManifests:
129129

130130
Optionally, set `service.internalTrafficPolicy: Local` or `Cluster` depending on your environment and how you want internal routing handled.
131131

132+
## Authenticating the Web UI with OIDC
133+
134+
Atlantis itself only ships HTTP Basic Auth (`basicAuth`) for the web UI. To put the UI behind an OIDC identity provider (Okta, Google, Entra ID, Keycloak, ...) you have two common options.
135+
136+
### Option 1: OIDC at the ingress / load balancer
137+
138+
If your ingress controller can perform OIDC itself, this is the least moving parts. For example, the AWS Load Balancer Controller can authenticate directly on the ALB via the `alb.ingress.kubernetes.io/auth-*` annotations. A full ALB IngressGroup example (one Ingress for the VCS webhooks, one for the OIDC-protected UI) is in [#346](https://github.com/runatlantis/helm-charts/issues/346).
139+
140+
### Option 2: An [oauth2-proxy](https://github.com/oauth2-proxy/oauth2-proxy) sidecar
141+
142+
This is portable across ingress controllers and clouds. The proxy runs alongside Atlantis, terminates the OIDC flow, and forwards authenticated requests to Atlantis on `localhost`.
143+
144+
The key thing to get right is that **VCS webhooks must not go through the auth proxy** — the webhook sender cannot complete an interactive login. So:
145+
146+
- Keep the default `service` port pointed at Atlantis (`targetPort: 4141`) and send webhooks there directly.
147+
- Add an extra service port that targets the proxy, and route only the browser-facing UI host/path to it.
148+
149+
Run the proxy as a native sidecar (`initContainers` with `restartPolicy: Always`, supported since the chart version that allows `restartPolicy` on containers) so it shares the Pod lifecycle, or as a plain `extraContainers` entry on older versions:
150+
151+
```yaml
152+
# Expose the proxy on a second service port; webhooks keep using the default port -> 4141.
153+
service:
154+
extraPorts:
155+
- name: atlantis-ui
156+
port: 8080
157+
protocol: TCP
158+
targetPort: oauth2-proxy
159+
160+
# Native sidecar (requires restartPolicy support). Use extraContainers instead on older charts.
161+
initContainers:
162+
- name: oauth2-proxy
163+
# renovate: image=oauth2-proxy/oauth2-proxy
164+
image: quay.io/oauth2-proxy/oauth2-proxy:v7.15.3-alpine
165+
restartPolicy: Always
166+
args:
167+
- --config=/etc/oauth2-proxy/oauth2-proxy.cfg
168+
env:
169+
- name: OAUTH2_PROXY_CLIENT_ID
170+
valueFrom:
171+
secretKeyRef:
172+
name: atlantis-oidc
173+
key: client-id
174+
- name: OAUTH2_PROXY_CLIENT_SECRET
175+
valueFrom:
176+
secretKeyRef:
177+
name: atlantis-oidc
178+
key: client-secret
179+
# 32-byte cookie secret, e.g. `openssl rand -base64 32 | head -c 32 | base64`
180+
- name: OAUTH2_PROXY_COOKIE_SECRET
181+
valueFrom:
182+
secretKeyRef:
183+
name: atlantis-oidc
184+
key: cookie-secret
185+
ports:
186+
- name: oauth2-proxy
187+
containerPort: 4180
188+
protocol: TCP
189+
volumeMounts:
190+
- name: oauth2-proxy-config
191+
mountPath: /etc/oauth2-proxy
192+
securityContext:
193+
allowPrivilegeEscalation: false
194+
readOnlyRootFilesystem: true
195+
runAsNonRoot: true
196+
capabilities:
197+
drop: [ALL]
198+
199+
extraVolumes:
200+
- name: oauth2-proxy-config
201+
configMap:
202+
name: oauth2-proxy-config
203+
```
204+
205+
Provide the proxy config via your own ConfigMap (here through `extraManifests`). The example below targets Okta; swap `oidc_issuer_url` for your provider:
206+
207+
```yaml
208+
extraManifests:
209+
- apiVersion: v1
210+
kind: ConfigMap
211+
metadata:
212+
name: oauth2-proxy-config
213+
data:
214+
oauth2-proxy.cfg: |
215+
provider="oidc"
216+
oidc_issuer_url="https://<your-org>.okta.com"
217+
# Atlantis listens on the service targetPort (4141 by default).
218+
upstreams=["http://localhost:4141"]
219+
http_address=":4180"
220+
redirect_url="https://atlantis.example.com/oauth2/callback"
221+
email_domains="*"
222+
cookie_secure="true"
223+
reverse_proxy="true"
224+
skip_provider_button="true"
225+
code_challenge_method="S256"
226+
# Optionally restrict access to specific IdP groups:
227+
# oidc_groups_claim="groups"
228+
# allowed_groups=["atlantis-admins"]
229+
```
230+
231+
Then point the browser-facing Ingress host at the `atlantis-ui` service port (`8080`) while the webhook URL configured in your VCS continues to hit the default port. If you prefer a single port instead, route everything through the proxy and let webhooks bypass auth with `skip_auth_routes=["POST=^/events$"]`.
232+
132233
{{ template "chart.valuesSection" . }}
133234

134235
## Upgrading

0 commit comments

Comments
 (0)