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/

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です