ingress-nginx で configuration-snippet と whitelist-source-range を使って ACL を設定する
ingress-nginx を使って作成した ingress リソースに annotations を定義し ACL を設定する方法について紹介します。
ingress の annotations に nginx.ingress.kubernetes.io/whitelist-source-range で allow リストと nginx.ingress.kubernetes.io/configuration-snippet で deny リストを設定することができます。
また、ingress リソースに対して ACL の設定をどのように管理しているのかについても紹介します。
公式ドキュメント
リポジトリ: https://github.com/kubernetes/ingress-nginx
ArtifuctHub: https://artifacthub.io/packages/helm/ingress-nginx/ingress-nginx
Helm Chart version: 4.11.3
モチベーション
- 悪意のあるリクエストに対して deny 設定をしたかった
- deny 設定について全ての ingress リソースに一括で適用したかった
Helm の values.yaml 設定
自宅環境では metallb と 組み合わせています。controller.service.loadBalancerIP には metallb のIPAddressPool で設定した IP アドレスを指定しています。
controller.service.externalTrafficPolicy: “local” とすることでアクセス元 IP を保持することができます。この設定を行うことで、外部からのアクセスに対して deny リストや allow リストで制御することができます。
controller.allowSnippetAnnotations: true にすることで ingress リソースで snippet に関する annotations の設定を有効にしています。
controller:
service:
loadBalancerIP: "192.168.1.100"
externalTrafficPolicy: "Local"
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 5
targetCPUUtilizationPercentage: 60
targetMemoryUtilizationPercentage: 70
allowSnippetAnnotations: true
クラウド環境ではプロバイダーのネットワークロードバランサーを利用し、ホストネットワークで 80 port と 443 port でリクエストを全てのホスト( DaemonSet )で受け付けるようにしています。
また、ホストネットワークで設定する場合は権限の設定( controller.containerSecurityContext )を追加する必要があります。
controller:
kind: DaemonSet
service:
loadBalancerIP: "10.0.0.100"
hostNetwork: true
containerSecurityContext:
capabilities:
add:
- NET_BIND_SERVICE
allowSnippetAnnotations: true
Ingress リソースの管理
Ingress リソースについては kustomize で管理しています。各ミドルウェアの Helm に Ingress の設定が内包されていることがありますが、ingress リソースのマニフェストを作成し集約して管理しています。そうすることで Kustomize の Overlays と commonAnnotations もしくは buildin の AnnotationsTransformer を使って一括で annotations を設定することで全ての ingress リソースに対して deny の設定を行っています。
ただ、spec.tls.0.hosts のリストに対して kustomize の PrefixSuffixTransformer でうまく設定できず、2重 Overlays 構成となっていています。
https://github.com/kubernetes-sigs/kustomize/issues/4884
production 環境と staging 環境の Kubernetes Cluster が分かれているのであれば シングル Overlays か Helm でシンプルに管理できると思います。
.
├── README.md
├── base
│ ├── ingress.yaml
│ └── kustomization.yaml
├── base-tls
│ ├── cluster-issuer.yaml
│ ├── ingress-tls.yaml
│ └── kustomization.yaml
├── overlay
│ ├── aimhighergg-com
│ │ ├── maintenance
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ ├── service.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── airflow
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── alertmanager
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── argocd
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── argocd-api
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── argoworkflows
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── consul
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── grafana
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── grafana-login
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── influxdb
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── jupyterlab
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── kubernetes-dashboard
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── loki-backend
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── loki-read
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── loki-write
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── loki-write-external
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── longhorn
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── maintenance
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── maintenance-redirect
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── mgmt
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ ├── service.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ ├── service.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── mimir
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── minio-loki
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── minio-mimir
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── prometheus
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── redmine
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── template
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ ├── vault
│ │ ├── production
│ │ │ ├── kustomization.yaml
│ │ │ └── transformer-suffixprefix.yaml
│ │ └── staging
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ └── wiki-aimhighergg-com
│ ├── production
│ │ ├── kustomization.yaml
│ │ └── transformer-suffixprefix.yaml
│ └── staging
│ ├── kustomization.yaml
│ └── transformer-suffixprefix.yaml
├── production
│ ├── kustomization.yaml
│ ├── transformer-annotations.yaml
│ ├── transformer-label.yaml
│ └── transformer-suffixprefix.yaml
└── staging
├── kustomization.yaml
├── transformer-annotations.yaml
├── transformer-label.yaml
└── transformer-suffixprefix.yaml
実行する kustomization.yaml に transformers で annotations を設定し、全ての resouces に nginx.ingress.kubernetes.io/configuration-snippet を設定し deny の設定を一括で適用しています。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../overlay/aimhighergg-com/production
- ../overlay/airflow/production
- ../overlay/alertmanager/production
- ../overlay/argocd/production
- ../overlay/argocd-api/production
- ../overlay/argoworkflows/production
- ../overlay/consul/production
- ../overlay/grafana/production
- ../overlay/grafana-login/production
- ../overlay/influxdb/production
- ../overlay/jupyterlab/production
- ../overlay/kubernetes-dashboard/production
- ../overlay/loki-backend/production
- ../overlay/loki-read/production
- ../overlay/loki-write/production
- ../overlay/loki-write-external/production
- ../overlay/longhorn/production
- ../overlay/mgmt/production
- ../overlay/mimir/production
- ../overlay/minio-loki/production
- ../overlay/minio-mimir/production
- ../overlay/prometheus/production
- ../overlay/redmine/production
- ../overlay/vault/production
- ../overlay/wiki-aimhighergg-com/production
transformers:
- transformer-annotations.yaml
- transformer-label.yaml
- transformer-suffixprefix.yaml
AnnotationsTransformer を使って annotations を Overlay で指定した resources に適用することで、ingress リソースに deny の IP アドレスを設定します。
また、サブネット単位( deny 192.168.1.0/24; )で設定することも可能です。
apiVersion: builtin
kind: AnnotationsTransformer
metadata:
name: annotations-transformer
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
deny 1.1.1.1;deny 2.2.2.2;deny 3.3.3.3;
fieldSpecs:
- kind: Ingress
path: metadata/annotations
許可設定については個別の ingress リソースに nginx.ingress.kubernetes.io/whitelist-source-range を定義します。以下では 2つ目の Overlays でパッチを当てています。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: longhorn-system
resources:
- ../../../base-tls
transformers:
- transformer-suffixprefix.yaml
patches:
- target:
version: v1
group: networking.k8s.io
name: ingress-tls
patch: |-
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-tls
annotations:
nginx.ingress.kubernetes.io/whitelist-source-range: 192.168.1.1/24
spec:
ingressClassName: nginx
tls:
- hosts:
- longhorn.aimhighergg.com
secretName: tls-secret
rules:
- host: longhorn.aimhighergg.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: longhorn-frontend
port:
number: 80
運用しているリポジトリ
ingress を集約して運用しています。
https://github.com/AbeYuki/ingress-aggregator
今回は ingress リソースに kustomize を使って annotations を一括で設定する方法を紹介しましたが、nginx-template を使ってグローバルに設定する方法もあります。
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/custom-template/