apache / apache/apisix-helm-chart

Admin API allowlist bypassed when ingress-controller enabled (+ missing IPv6)

Open
#921 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Go Template
Stars
289
Forks
282
Avg merge
15h 55m
Merged PRs (30d)
3

Description

## Description
The admin API allowlist logic in `templates/configmap.yaml` has two critical issues when `ingress-controller.enabled: true`:

1. **Security bypass**: User-specified allowlist is overridden by unconditionally appending `0.0.0.0/0`
2. **Missing IPv6 support**: Only `0.0.0.0/0` is added, breaking IPv6-only clusters

## Environment
- Helm Chart Version: 2.12.4
- Kubernetes Version: 1.34
- Helm Version: 3.18.4 (through Terraform's Helm provider)

## Current Behavior

The template always appends `0.0.0.0/0` when ingress-controller is enabled:

```yaml
allow_admin:
{{- if .Values.apisix.admin.allow.ipList }}
{{- range $ips := .Values.apisix.admin.allow.ipList }}
- {{ $ips }}
{{- end }}
{{- else }}
- 0.0.0.0/0
{{- end}}
{{- if (index .Values "ingress-controller" "enabled") }}
- 0.0.0.0/0 # Always appended - overrides user security
{{- end}}
```

**Default `values.yaml`:**
```yaml
apisix:
admin:
allow:
ipList:
- 127.0.0.1/24 # Secure default - localhost only
```

---

> **⚠️ Edge Case Note:**
> Currently, an empty `ipList: []` defaults to `0.0.0.0/0` via the `{{- else }}` branch. This is likely unintentional behavior, but exists in production. All proposed options below change this edge case.

## Problem 1: Security Bypass

### Steps to Reproduce
1. Configure values.yaml with restricted allowlist:
```yaml
apisix:
admin:
allow:
ipList:
- 10.244.0.0/16 # Restrict to pod network only
ingress-controller:
enabled: true
```
2. Deploy the chart: `helm install apisix apisix/apisix -f values.yaml`
3. Check the generated ConfigMap: `kubectl get configmap apisix -o yaml`

### Expected Behavior
Admin API should only be accessible from `10.244.0.0/16`:
```yaml
allow_admin:
- 10.244.0.0/16
```

### Actual Behavior
User's restriction is bypassed:
```yaml
allow_admin:
- 10.244.0.0/16
- 0.0.0.0/0 # Unconditionally added - allows all traffic
```

### Impact
Users cannot properly secure the admin API through the allowlist when using ingress-controller. Security hardening attempts are silently ignored.

**Example with default values:**
```yaml
# User expects: localhost only
allow_admin:
- 127.0.0.1/24 # Secure default
- 0.0.0.0/0 # Auto-added - silently weakens security!
```

---

## Problem 2: IPv6 Not Supported

### Steps to Reproduce
1. Deploy to an IPv6-only Kubernetes cluster
2. Enable ingress-controller with default settings
3. Check ingress-controller pod logs

### Expected Behavior
Ingress-controller should be able to access the admin API using its IPv6 address.

### Actual Behavior
Access is denied because the allowlist only includes `0.0.0.0/0` (IPv4):
```
[error] access forbidden by rule, client: [2001:db8::1]
```

### Impact
Chart is non-functional in IPv6-only clusters without manual workarounds.

---

## Proposed Solutions

I see three potential approaches, each with different tradeoffs:

### Option A: Always Append (Fixes IPv6, Maintains Current Behavior)

```yaml
allow_admin:
{{- range $ips := .Values.apisix.admin.allow.ipList }}
- {{ $ips | quote }}
{{- end }}
{{- if (index .Values "ingress-controller" "enabled") }}
- 0.0.0.0/0
- "::/0"
{{- end }}
```

**Pros:**
- Minimal change - most backward compatible
- Fixes IPv6 support
- Simple logic

**Cons:**
- Still overrides user security (documents the issue but doesn't fix it)
- Users with custom `ipList` still get wildcards appended

**Breaking Changes:**
- Empty `ipList: []` no longer defaults to allow-all (see edge case note above)
- Otherwise maintains current behavior + adds IPv6

---

### Option B: Respect User Configuration (Most Secure)

```yaml
allow_admin:
{{- if .Values.apisix.admin.allow.ipList }}
{{- range $ips := .Values.apisix.admin.allow.ipList }}
- {{ $ips | quote }}
{{- end }}
{{- else }}
{{- if (index .Values "ingress-controller" "enabled") }}
- 0.0.0.0/0
- "::/0"
{{- end }}
{{- end }}
```

**Pros:**
- Respects user security choices
- No more silent security bypass
- IPv6 support in defaults

**Cons:**
- Breaking change for users relying on the current buggy behavior
- Users must explicitly allow ingress-controller access when using custom `ipList`

**Breaking Changes:**
- Empty `ipList: []` no longer defaults to allow-all (see edge case note above)
- Users with custom `ipList` who relied on auto-added `0.0.0.0/0` must add it explicitly

```yaml
apisix:
admin:
allow:
ipList:
- 10.244.0.0/16 # Custom restriction
- 0.0.0.0/0 # Must add explicitly for ingress-controller (if cidr is unknown)
- "::/0" # IPv6 support
```

---

### Option C: Make It Configurable (Future-Proof)

Add new value to control behavior:
```yaml
apisix:
admin:
allow:
ipList:
- 127.0.0.1/24
autoAddIngressControllerAccess: true # New option (default: true)
```

Template logic:
```yaml
allow_admin:
{{- range $ips := .Values.apisix.admin.allow.ipList }}
- {{ $ips | quote }}
{{- end }}
{{- if and (index .Values "ingress-controller" "enabled") .Values.apisix.admin.allow.autoAddIngressControllerAccess }}
- 0.0.0.0/0
- "::/0"
{{- end }}
```

**Pros:**
- Gives users explicit control
- Backward compatible (default: true maintains current behavior)
- Clear and self-documenting
- Easy to disable for security-conscious users

**Cons:**
- More complex (adds new configuration option)
- Requires documentation updates

**Breaking Changes:**
- Empty `ipList: []` no longer defaults to allow-all (see edge case note above)

---

## Recommendation

I'm inclined to suggest **Option C** as it balances all concerns:
- Fixes IPv6 support
- Maintains backward compatibility
- Gives users control over security
- Makes behavior explicit and documented

However, I'm happy to implement whichever approach is preferred.

**I'm also happy to submit a PR for this fix, combined with my other issue (#920) about IPv6 quoting since both touch the same ConfigMap template file.**

---
*Note: AI helped format this issue. The issue identification and proposed solutions are my own work.*

Contributor guide

No contributing guide indexed for this repository

Research direction

Start in templates/configmap.yaml and compare the allow_admin rendering with the documented values and ingress-controller settings. Render the chart with Helm using a restricted ipList, an empty list, ingress enabled, and IPv6-related values, then inspect the generated ConfigMap. Done means the maintainer-selected behavior is explicit, preserves intended restrictions, and covers both IPv4 and IPv6 access.

Written by the indexing model from the issue text.

Assessment

Tech stack
helm, kubernetes
Domain
devops, infrastructure, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.