From 891858f52f5b6737b0e492dc73998b58210e0c98 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Fri, 22 Mar 2024 17:17:29 +0000
Subject: [PATCH 01/38] refactor main CI workflow
---
.github/workflows/azure-upload.yml | 43 ++
.github/workflows/build-oss.yml | 171 +++-----
.github/workflows/build-plus.yml | 225 ++++------
.github/workflows/cache-update.yml | 57 +--
.github/workflows/ci.yml | 524 ++++++++++-------------
.github/workflows/create-release-tag.yml | 56 ---
.github/workflows/edge.yml | 303 +++++++++++++
.github/workflows/release.yml | 297 +++++++++++++
8 files changed, 1019 insertions(+), 657 deletions(-)
create mode 100644 .github/workflows/azure-upload.yml
delete mode 100644 .github/workflows/create-release-tag.yml
create mode 100644 .github/workflows/edge.yml
create mode 100644 .github/workflows/release.yml
diff --git a/.github/workflows/azure-upload.yml b/.github/workflows/azure-upload.yml
new file mode 100644
index 0000000000..b2d818233f
--- /dev/null
+++ b/.github/workflows/azure-upload.yml
@@ -0,0 +1,43 @@
+name: Upload NIC Release to Azure
+
+on:
+ push:
+ branches:
+ - image-build-refactor
+
+defaults:
+ run:
+ shell: bash
+
+permissions:
+ contents: read
+
+jobs:
+ azure-upload:
+ name: Upload packages to Azure
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+
+ - name: Fetch Cached Package Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ key: nginx-ingress-d2052fb01bb850127dd02aaaa6c790a9
+ path: dist
+ fail-on-cache-miss: true
+
+ - name: Azure Login
+ uses: azure/login@8c334a195cbb38e46038007b304988d888bf676a # v2.0.0
+ with:
+ creds: ${{ secrets.AZURE_STORAGE_KEY }}
+
+ - name: Azure Upload Release Packages
+ uses: azure/CLI@965c8d7571d2231a54e321ddd07f7b10317f34d9 # v2.0.0
+ with:
+ inlineScript: |
+ for i in ./dist*; do
+ echo "Uploading ${i} to kubernetes-ingress/v0.0.0/${i##*/}"
+ az storage blob upload --auth-mode=login -f "$i" -c ${{ secrets.AZURE_BUCKET_NAME }} \
+ --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT }} --overwrite -n kubernetes-ingress/v0.0.0/${i##*/}
+ done
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index e6b4618901..fea450ab15 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -9,20 +9,23 @@ on:
image:
required: true
type: string
+ tag:
+ required: false
+ type: string
go-md5:
required: true
type: string
base-image-md5:
- required: false
+ required: true
type: string
- tag:
- required: false
+ branch:
+ required: true
type: string
- publish-image:
- required: false
- type: boolean
forked-workflow:
- required: false
+ required: true
+ type: boolean
+ docs-only:
+ required: true
type: boolean
defaults:
@@ -38,69 +41,23 @@ jobs:
permissions:
contents: read # for docker/build-push-action to read repo content
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
- id-token: write # for OIDC login to AWS ECR
+ id-token: write # for OIDC login to GCR
packages: write # for docker/build-push-action to push to GHCR
- outputs:
- version: ${{ steps.meta.outputs.version }}
- image_digest: ${{ steps.build-push.outputs.digest }}
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
- ref: ${{ inputs.tag != '' && format('refs/tags/v{0}', inputs.tag) || github.ref }}
+ ref: ${{ inputs.branch }}
fetch-depth: 0
- - name: Fetch Cached Artifacts
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ inputs.go-md5 }}
-
- name: Setup QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
with:
platforms: arm,arm64,ppc64le,s390x
- if: ${{ inputs.publish-image }}
- name: Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
- - name: DockerHub Login
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- username: ${{ secrets.DOCKER_USERNAME }}
- password: ${{ secrets.DOCKER_PASSWORD }}
- if: ${{ inputs.publish-image }}
-
- - name: Login to GitHub Container Registry
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: ghcr.io
- username: ${{ github.repository_owner }}
- password: ${{ secrets.GITHUB_TOKEN }}
- if: ${{ inputs.publish-image }}
-
- - name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
- with:
- aws-region: us-east-1
- role-to-assume: ${{ secrets.AWS_ROLE_PUBLIC_ECR }}
- if: ${{ inputs.publish-image }}
-
- - name: Login to Public ECR
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: public.ecr.aws
- if: ${{ inputs.publish-image }}
-
- - name: Login to Quay.io
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: quay.io
- username: ${{ secrets.QUAY_USERNAME }}
- password: ${{ secrets.QUAY_ROBOT_TOKEN }}
- if: ${{ inputs.publish-image }}
-
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
@@ -108,7 +65,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ ! inputs.forked-workflow }}
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -116,7 +73,7 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ ! inputs.forked-workflow }}
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
- name: Check if base images exist
id: base_exists
@@ -126,7 +83,7 @@ jobs:
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ ! inputs.forked-workflow }}
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
- name: Build Base Container
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
@@ -143,38 +100,19 @@ jobs:
build-args: |
BUILD_OS=${{ inputs.image }}
IC_VERSION=${{ inputs.tag }}
- if: ${{ ! inputs.forked-workflow && steps.base_exists.outputs.exists != 0 }}
-
- - name: Get short tag
- id: tag
- run: |
- version="${{ inputs.tag }}"
- short="${version%.*}"
- echo "short=$short" >> $GITHUB_OUTPUT
- if: ${{ inputs.tag != '' }}
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.base_exists.outputs.exists != 0 }}
- name: Docker meta
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
with:
- context: ${{ inputs.tag != '' && 'git' || 'workflow' }}
+ context: workflow
images: |
- name=nginx/nginx-ingress
- name=ghcr.io/nginxinc/kubernetes-ingress
- name=public.ecr.aws/nginx/nginx-ingress
- name=quay.io/nginx/nginx-ingress
+ name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
flavor: |
- latest=${{ (inputs.tag != '' && 'true') || 'auto' }}
- suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }},onlatest=true
+ suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}
tags: |
- type=edge
- type=ref,event=pr
- type=ref,event=branch,enable=${{ startsWith(github.ref, 'refs/heads/release-') }}
- type=schedule,enable=${{ inputs.tag == '' }}
- type=semver,pattern={{version}}
- type=semver,pattern={{major}}.{{minor}}
- type=raw,value=${{ inputs.tag }},enable=${{ inputs.tag != '' }}
- type=raw,value=${{ steps.tag.outputs.short }},enable=${{ inputs.tag != '' }}
+ type=raw,value=${{ inputs.tag }}
labels: |
org.opencontainers.image.description=NGINX Ingress Controller for Kubernetes
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/main/README.md
@@ -185,6 +123,32 @@ jobs:
env:
DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
+ - name: Check if target image exists
+ id: target_exists
+ run: |
+ if docker pull ${{ steps.meta.outputs.tags }}; then
+ echo "exists=0" >> $GITHUB_OUTPUT
+ else
+ echo "exists=1" >> $GITHUB_OUTPUT
+ fi
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+
+ - name: Debug values
+ run: |
+ echo "forked-workflow: ${{ inputs.forked-workflow }}"
+ echo "docs-only: ${{ inputs.docs-only }}"
+ echo "docs-only invert: ${{ ! inputs.docs-only }}"
+ echo "base_exists: ${{ steps.base_exists.outputs.exists }}"
+ echo "target_exists: ${{ steps.target_exists.outputs.exists }}"
+ echo "all: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
+
+ - name: Fetch Cached Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ inputs.go-md5 }}
+ if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+
- name: Build Docker image
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
id: build-push
@@ -196,32 +160,19 @@ jobs:
target: goreleaser${{ ! inputs.forked-workflow && '-prebuilt' || '' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- annotations: ${{ github.event_name != 'pull_request' && steps.meta.outputs.annotations || '' }}
- platforms: ${{ github.event_name != 'pull_request' && ! startsWith(github.ref, 'refs/heads/release-') && inputs.platforms || '' }}
- load: ${{ github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/release-') }}
- push: ${{ inputs.publish-image }}
+ annotations: ${{ steps.meta.outputs.annotations }}
+ platforms: ${{ inputs.platforms }}
+ load: false
+ push: ${{ ! inputs.forked-workflow }}
pull: true
- no-cache: ${{ inputs.publish-image }}
- sbom: ${{ inputs.publish-image }}
+ no-cache: ${{ ! inputs.forked-workflow }}
+ sbom: ${{ ! inputs.forked-workflow }}
provenance: false
build-args: |
BUILD_OS=${{ inputs.image }}
${{ ! inputs.forked-workflow && format('PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:{0}-{1}', inputs.base-image-md5, inputs.image) || '' }}
IC_VERSION=${{ (github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/release-')) && 'CI' || steps.meta.outputs.version }}
-
- - name: Certify Images
- continue-on-error: true
- run: |
- curl -fsSL https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/1.6.11/preflight-linux-amd64 --output preflight
- chmod +x preflight
-
- IFS=',' read -ra arch_list <<< "${{ inputs.platforms }}"
-
- for arch in "${arch_list[@]}"; do
- architecture=("${arch#*/}")
- ./preflight check container quay.io/nginx/nginx-ingress:${{ steps.meta.outputs.version }} --pyxis-api-token ${{ secrets.PYXIS_API_TOKEN }} --certification-project-id ${{ secrets.CERTIFICATION_PROJECT_ID }} --platform $architecture --submit
- done
- if: ${{ github.ref_type == 'tag' && contains(inputs.image, 'ubi') }}
+ if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0
@@ -231,12 +182,14 @@ jobs:
format: "sarif"
output: "trivy-results-${{ inputs.image }}.sarif"
ignore-unfixed: "true"
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
continue-on-error: true
with:
sarif_file: "trivy-results-${{ inputs.image }}.sarif"
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Upload Scan Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
@@ -245,17 +198,3 @@ jobs:
name: "trivy-results-${{ inputs.image }}.sarif"
path: "trivy-results-${{ inputs.image }}.sarif"
if: always()
-
- send-notification:
- name: Send Notification
- needs: build
- uses: ./.github/workflows/updates-notification.yml
- with:
- tag: ${{ inputs.tag }}
- version: ${{ needs.build.outputs.version }}
- image_digest: ${{ needs.build.outputs.image_digest }}
- permissions:
- contents: read
- actions: read
- secrets: inherit
- if: ${{ inputs.tag != '' }}
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 53f56eed9f..8a0f507e20 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -9,8 +9,8 @@ on:
image:
required: true
type: string
- target:
- required: true
+ tag:
+ required: false
type: string
go-md5:
required: true
@@ -18,23 +18,20 @@ on:
base-image-md5:
required: false
type: string
- nap_modules:
- required: false
- type: string
- release-url:
+ branch:
required: false
type: string
- publish-image:
- required: false
- type: boolean
- publish-aws-market-place:
- required: false
- type: boolean
- publish-nginx-reqistry:
+ forked-workflow:
required: false
type: boolean
- forked-workflow:
+ nap-modules:
required: false
+ type: string
+ target:
+ required: true
+ type: string
+ docs-only:
+ required: true
type: boolean
defaults:
@@ -50,24 +47,18 @@ jobs:
contents: read # for docker/build-push-action to read repo content
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
id-token: write # for OIDC login to AWS
- runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-22.04' || 'kic-plus' }}
+ runs-on: ubuntu-22.04
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
+ ref: ${{ inputs.branch }}
fetch-depth: 0
- - name: Fetch Cached Artifacts
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ inputs.go-md5 }}
-
- name: Setup QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
with:
platforms: arm64,s390x
- if: ${{ inputs.publish-image }}
- name: Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
@@ -79,7 +70,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ inputs.publish-image || ! inputs.forked-workflow }}
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -87,78 +78,26 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ inputs.publish-image || ! inputs.forked-workflow }}
-
- - name: Configure AWS Credentials
- uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2
- with:
- aws-region: us-east-1
- role-to-assume: ${{ secrets.AWS_ROLE_MARKETPLACE }}
- if: ${{ inputs.publish-aws-market-place }}
- - name: Login to ECR
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: 709825985650.dkr.ecr.us-east-1.amazonaws.com
- if: ${{ inputs.publish-aws-market-place }}
-
- - name: Get Id Token
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
- id: idtoken
- with:
- script: |
- let id_token = await core.getIDToken()
- core.setOutput('id_token', id_token)
- if: ${{ inputs.publish-nginx-reqistry }}
-
- - name: Login to NGINX Registry
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: docker-mgmt.nginx.com
- username: ${{ steps.idtoken.outputs.id_token }}
- password: ${{ github.actor }}
- if: ${{ inputs.publish-nginx-reqistry }}
-
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
- with:
- images: |
- name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(inputs.nap_modules, 'dos') && '-dos' || '' }}${{ contains(inputs.nap_modules, 'waf') && '-nap' || '' }}/nginx-plus-ingress
- name=docker-mgmt.nginx.com/nginx-ic${{ contains(inputs.nap_modules, 'waf') && '-nap' || '' }}${{ contains(inputs.nap_modules, 'dos') && '-dos' || '' }}/nginx-plus-ingress,enable=${{ inputs.publish-nginx-reqistry && ! contains(inputs.target, 'aws') }}
- name=709825985650.dkr.ecr.us-east-1.amazonaws.com/nginx/nginx-plus-ingress${{ contains(inputs.nap_modules, 'dos') && '-dos' || '' }}${{ contains(inputs.nap_modules, 'waf') && '-nap' || '' }},enable=${{ inputs.publish-aws-market-place && contains(inputs.target, 'aws') }}
- flavor: |
- suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}${{ contains(inputs.target, 'aws') && '-mktpl' || '' }}${{ contains(inputs.image, 'fips') && '-fips' || ''}},onlatest=true
- latest=${{ contains(inputs.target, 'aws') && 'false' || 'auto' }}
- tags: |
- type=edge
- type=ref,event=pr
- type=ref,event=branch,enable=${{ startsWith(github.ref, 'refs/heads/release-') }}
- type=schedule
- type=semver,pattern={{version}}
- type=semver,pattern={{major}}.{{minor}}
- labels: |
- org.opencontainers.image.description=NGINX Plus Ingress Controller for Kubernetes
- env:
- DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
- name: NAP modules
id: nap_modules
run: |
- [[ "${{ inputs.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || name="${{ inputs.nap_modules }}"
- [[ "${{ inputs.nap_modules }}" == "waf,dos" ]] && modules="both" || modules="${{ inputs.nap_modules }}"
+ [[ "${{ inputs.nap-modules }}" == "waf,dos" ]] && modules="waf-dos" || name="${{ inputs.nap-modules }}"
+ [[ "${{ inputs.nap-modules }}" == "waf,dos" ]] && modules="both" || modules="${{ inputs.nap-modules }}"
echo "modules=${modules}" >> $GITHUB_OUTPUT
echo "name=${name}" >> $GITHUB_OUTPUT
- if: ${{ inputs.nap_modules != '' }}
+ if: ${{ inputs.nap-modules != '' }}
- name: Check if base images exist
id: base_exists
run: |
- if docker manifest inspect gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}; then
+ if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ ! inputs.forked-workflow }}
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
- name: Build Base Container
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
@@ -174,16 +113,58 @@ jobs:
push: true
build-args: |
BUILD_OS=${{ inputs.image }}
- IC_VERSION=${{ github.ref_type == 'tag' && steps.meta.outputs.version || 'CI' }}
- ${{ steps.nap_modules.outputs.modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
+ IC_VERSION=${{ steps.meta.outputs.version }}
+ ${{ inputs.nap-modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
secrets: |
- "nginx-repo.crt=${{ inputs.nap_modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
- "nginx-repo.key=${{ inputs.nap_modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
- ${{ inputs.nap_modules != '' && contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ ! inputs.forked-workflow && steps.base_exists.outputs.exists != 0 }}
+ "nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
+ "nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
+ ${{ inputs.nap-modules != '' && contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.base_exists.outputs.exists != 0 }}
- - name: Build Plus Docker image
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
+ with:
+ images: |
+ name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(inputs.nap-modules, 'dos') && '-dos' || '' }}${{ contains(inputs.nap-modules, 'waf') && '-nap' || '' }}/nginx-plus-ingress
+ flavor: |
+ suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}${{ contains(inputs.target, 'aws') && '-mktpl' || '' }}${{ contains(inputs.image, 'fips') && '-fips' || ''}}
+ tags: |
+ type=raw,value=${{ inputs.tag }}
+ labels: |
+ org.opencontainers.image.description=NGINX Plus Ingress Controller for Kubernetes
+ env:
+ DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
+
+ - name: Check if target image exists
+ id: target_exists
+ run: |
+ if docker pull ${{ steps.meta.outputs.tags }}; then
+ echo "exists=0" >> $GITHUB_OUTPUT
+ else
+ echo "exists=1" >> $GITHUB_OUTPUT
+ fi
+ if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+
+ - name: Debug values
+ run: |
+ echo "forked-workflow: ${{ inputs.forked-workflow }}"
+ echo "docs-only: ${{ inputs.docs-only }}"
+ echo "docs-only invert: ${{ ! inputs.docs-only }}"
+ echo "base_exists: ${{ steps.base_exists.outputs.exists }}"
+ echo "target_exists: ${{ steps.target_exists.outputs.exists }}"
+ echo "all: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
+
+ - name: Fetch Cached Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ inputs.go-md5 }}
+ if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+
+ - name: Build Docker image
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ id: build-push
with:
file: build/Dockerfile
context: "."
@@ -192,66 +173,32 @@ jobs:
target: ${{ inputs.target }}${{ ! inputs.forked-workflow && '-prebuilt' || '' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- annotations: ${{ inputs.publish-image && steps.meta.outputs.annotations || '' }}
- platforms: ${{ inputs.publish-image && inputs.platforms || '' }}
- load: ${{ ! inputs.publish-image }}
- push: ${{ inputs.publish-image }}
+ annotations: ${{ steps.meta.outputs.annotations }}
+ platforms: ${{ inputs.platforms }}
+ load: false
+ push: ${{ ! inputs.forked-workflow }}
pull: true
- no-cache: ${{ inputs.publish-image }}
- sbom: ${{ inputs.publish-image }}
+ no-cache: ${{ ! inputs.forked-workflow }}
+ sbom: ${{ ! inputs.forked-workflow }}
provenance: false
build-args: |
BUILD_OS=${{ inputs.image }}
- PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
- IC_VERSION=${{ github.ref_type == 'tag' && steps.meta.outputs.version || 'CI' }}
- ${{ inputs.nap_modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
+ ${{ ! inputs.forked-workflow && format('PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:{0}-{1}{2}', inputs.base-image-md5, inputs.image, steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '') || '' }}
+ IC_VERSION=${{ steps.meta.outputs.version }}
+ ${{ inputs.nap_modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
${{ (contains(inputs.target, 'aws') && inputs.nap_modules != '') && format('NAP_MODULES_AWS={0}', steps.nap_modules.outputs.modules) || '' }}
secrets: |
- "nginx-repo.crt=${{ inputs.nap_modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
- "nginx-repo.key=${{ inputs.nap_modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
- ${{ inputs.nap_modules != '' && contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
-
- - name: AWS variables
- id: aws
- run: |
- aws_registry=$(echo "${{ steps.meta.outputs.tags }}" | grep -oP "709825985650.dkr.ecr.us-east-1.amazonaws.com/[^[:space:]]+:${{ steps.meta.outputs.version }}")
- version=$(echo ${{ steps.meta.outputs.version }} | sed 's/-mktpl//')
- declare -A nap_mapping=(
- ["waf"]=_NAP_WAF
- ["dos"]=_NAP_DOS
- ["waf,dos"]=_NAP_WAF_DOS
- )
- modules=${{ inputs.nap_modules }}
- [[ -n $modules && ${nap_mapping[$modules]+_} ]] && nap=${nap_mapping[$modules]}
-
- echo "version=$version" >> $GITHUB_OUTPUT
- echo "product_code=AWS${nap}_PRODUCT_ID" >> $GITHUB_OUTPUT
- echo "registry=${aws_registry}" >> $GITHUB_OUTPUT
- if: ${{ inputs.publish-aws-market-place }}
-
- - name: Publish to AWS Marketplace
- uses: nginxinc/aws-marketplace-publish@be512a7ae9666098bc4429a1afa27a11be6a3995 # v1.0.3
- continue-on-error: true
- with:
- version: ${{ steps.aws.outputs.version }}
- product-id: ${{ secrets[steps.aws.outputs.product_code] }}
- registry: ${{ steps.aws.outputs.registry }}
- release-notes: ${{ inputs.release-url }}
- description: |
- Best-in-class traffic management solution for services in Amazon EKS.
- This is the official implementation of NGINX Ingress Controller (based on NGINX Plus) from NGINX.
- usage-instructions: |
- This container requires Kubernetes and can be deployed to EKS.
- Review the installation instructions https://docs.nginx.com/nginx-ingress-controller/installation/ and utilize the deployment resources available https://github.com/nginxinc/kubernetes-ingress/tree/master/deployments
- Use this image instead of building your own.
- if: ${{ inputs.publish-aws-market-place }}
+ "nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
+ "nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
+ ${{ contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
+ if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
- name: Extract image name for Trivy
id: trivy-tag
run: |
tag=$(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '[ .tags[] | select(contains("f5-gcs-7899"))] | .[0]')
echo "tag=$tag" >> $GITHUB_OUTPUT
- if: ${{ inputs.publish-image }}
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0
@@ -261,14 +208,14 @@ jobs:
format: "sarif"
output: "trivy-results-${{ inputs.image }}.sarif"
ignore-unfixed: "true"
- if: ${{ inputs.publish-image }}
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
continue-on-error: true
with:
sarif_file: "trivy-results-${{ inputs.image }}.sarif"
- if: ${{ inputs.publish-image }}
+ if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Upload Scan Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
diff --git a/.github/workflows/cache-update.yml b/.github/workflows/cache-update.yml
index c3a6c4f201..e5f828bd9e 100644
--- a/.github/workflows/cache-update.yml
+++ b/.github/workflows/cache-update.yml
@@ -21,7 +21,6 @@ jobs:
outputs:
go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
docker_md5: ${{ steps.vars.outputs.docker_md5 }}
- chart_version: ${{ steps.vars.outputs.chart_version }}
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
@@ -32,46 +31,8 @@ jobs:
./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
./.github/scripts/variables.sh docker_md5 >> $GITHUB_OUTPUT
source .github/data/version.txt
- echo "chart_version=${HELM_CHART_VERSION}" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
- release-notes:
- name: Release Notes
- runs-on: ubuntu-22.04
- needs: checks
- outputs:
- release-url: ${{ steps.release-notes.outputs.release-url }}
- permissions:
- contents: write # for lucacome/draft-release
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- fetch-depth: 0
-
- - name: Create/Update Draft
- uses: lucacome/draft-release@8a63d32c79a171ae6048e614a8988f0ac3ed56d4 # v1.1.0
- id: release-notes
- with:
- minor-label: "enhancement"
- major-label: "change"
- publish: ${{ github.ref_type == 'tag' }}
- collapse-after: 50
- variables: |
- helm-chart=${{ needs.checks.outputs.chart_version }}
- notes-footer: |
- ## Upgrade
- - For NGINX, use the {{version}} images from our [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/tags?page=1&ordering=last_updated&name={{version-number}}), [GitHub Container](https://github.com/nginxinc/kubernetes-ingress/pkgs/container/kubernetes-ingress), [Amazon ECR Public Gallery](https://gallery.ecr.aws/nginx/nginx-ingress) or [Quay.io](https://quay.io/repository/nginx/nginx-ingress).
- - For NGINX Plus, use the {{version}} images from the F5 Container registry, the [AWS Marketplace](https://aws.amazon.com/marketplace/search/?CREATOR=741df81b-dfdc-4d36-b8da-945ea66b522c&FULFILLMENT_OPTION_TYPE=CONTAINER&filters=CREATOR%2CFULFILLMENT_OPTION_TYPE), the [GCP Marketplace](https://console.cloud.google.com/marketplace/browse?filter=partner:F5,%20Inc.&filter=solution-type:k8s&filter=category:networking) or build your own image using the {{version}} source code.
- - For Helm, use version {{helm-chart}} of the chart.
-
- ## Resources
- - Documentation -- https://docs.nginx.com/nginx-ingress-controller/
- - Configuration examples -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/examples
- - Helm Chart -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/charts/nginx-ingress
- - Operator -- https://github.com/nginxinc/nginx-ingress-helm-operator
- if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
-
build-docker:
name: Build Docker OSS
needs: [checks]
@@ -90,8 +51,10 @@ jobs:
image: ${{ matrix.image }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- publish-image: false
forked-workflow: true
+ docs-only: false
+ tag: "edge"
+ branch: ${{ github.ref }}
permissions:
contents: read
actions: read
@@ -102,7 +65,7 @@ jobs:
build-docker-plus:
name: Build Docker Plus
- needs: [checks, release-notes]
+ needs: [checks]
strategy:
fail-fast: false
matrix:
@@ -120,8 +83,9 @@ jobs:
target: ${{ matrix.target }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- release-url: ${{ needs.release-notes.outputs.release-url }}
- publish-image: false
+ docs-only: false
+ tag: "edge"
+ branch: ${{ github.ref }}
forked-workflow: true
permissions:
contents: read
@@ -131,7 +95,7 @@ jobs:
build-docker-nap:
name: Build Docker NAP
- needs: [checks, release-notes]
+ needs: [checks]
strategy:
fail-fast: false
matrix:
@@ -176,8 +140,9 @@ jobs:
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
nap_modules: ${{ matrix.nap_modules }}
- release-url: ${{ needs.release-notes.outputs.release-url }}
- publish-image: false
+ docs-only: false
+ tag: "edge"
+ branch: ${{ github.ref }}
forked-workflow: true
permissions:
contents: read
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e784f987e9..b4c1b19ab8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,21 +5,11 @@ on:
branches:
- main
- release-*
- tags:
- - "v[0-9]+.[0-9]+.[0-9]+"
pull_request:
branches:
- main
- release-*
merge_group:
- schedule:
- - cron: "0 4 * * *" # run every day at 04:00 UTC
- workflow_dispatch:
- inputs:
- publish-image:
- description: Publish of the generated images
- type: boolean
- default: false
defaults:
run:
@@ -36,6 +26,9 @@ jobs:
checks:
name: Checks and variables
runs-on: ubuntu-22.04
+ permissions:
+ contents: read
+ id-token: write
outputs:
docs_only: ${{ github.event.pull_request && steps.docs.outputs.docs_only == 'true' }}
k8s_latest: ${{ steps.vars.outputs.k8s_latest }}
@@ -45,11 +38,11 @@ jobs:
binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
chart_version: ${{ steps.vars.outputs.chart_version }}
ic_version: ${{ steps.vars.outputs.ic_version }}
- publish_images: ${{ steps.vars.outputs.publish }}
docker_md5: ${{ steps.vars.outputs.docker_md5 }}
build_tag: ${{ steps.vars.outputs.build_tag }}
stable_tag: ${{ steps.vars.outputs.stable_tag }}
forked_workflow: ${{ steps.vars.outputs.forked_workflow }}
+ stable_image_exists: ${{ steps.stable_exists.outputs.exists }}
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
@@ -104,15 +97,6 @@ jobs:
echo "ic_version=${IC_VERSION}" >> $GITHUB_OUTPUT
echo "chart_version=${HELM_CHART_VERSION}" >> $GITHUB_OUTPUT
echo "forked_workflow=${{ (github.event.pull_request && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) || github.repository != 'nginxinc/kubernetes-ingress' }}" >> $GITHUB_OUTPUT
- publish=false
- if ${{ github.event_name == 'workflow_dispatch' && inputs.publish-image }}; then
- publish=true
- elif ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/heads/release-') }}; then
- publish=true
- elif ${{ github.event_name != 'workflow_dispatch' && github.event_name != 'pull_request' && ! startsWith(github.ref, 'refs/heads/release-') }}; then
- publish=true
- fi
- echo "publish=$publish" >> $GITHUB_OUTPUT
./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
./.github/scripts/variables.sh docker_md5 >> $GITHUB_OUTPUT
./.github/scripts/variables.sh build_tag >> $GITHUB_OUTPUT
@@ -139,6 +123,33 @@ jobs:
make update-codegen && git diff --name-only --exit-code pkg/**
cd ../../.. && mv github.com/nginxinc/kubernetes-ingress kubernetes-ingress/kubernetes-ingress
+ - name: Authenticate to Google Cloud
+ id: auth
+ uses: google-github-actions/auth@55bd3a7c6e2ae7cf1877fd1ccb9d54c0503c457c # v2.1.2
+ with:
+ token_format: access_token
+ workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
+
+ - name: Login to GCR
+ uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
+ with:
+ registry: gcr.io
+ username: oauth2accesstoken
+ password: ${{ steps.auth.outputs.access_token }}
+ if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
+
+ - name: Check if stable image exists
+ id: stable_exists
+ run: |
+ if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress:${{ steps.vars.outputs.stable_tag }}; then
+ echo "exists=0" >> $GITHUB_OUTPUT
+ else
+ echo "exists=1" >> $GITHUB_OUTPUT
+ fi
+ if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
+
unit-tests:
name: Unit Tests
runs-on: ubuntu-22.04
@@ -146,14 +157,17 @@ jobs:
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
- name: Setup Golang Environment
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
with:
go-version-file: go.mod
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
+
- name: Run Tests
run: make cover
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
+
- name: Upload coverage to Codecov
uses: codecov/codecov-action@125fc84a9a348dbcf27191600683ec096ec9021c # v4.4.1
with:
@@ -230,7 +244,7 @@ jobs:
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
with:
version: latest
- args: ${{ github.ref_type == 'tag' && 'release' || 'build --snapshot' }} ${{ github.event_name == 'pull_request' && '--single-target' || '' }} --clean
+ args: ${{ github.ref_type == 'tag' && 'release' || 'build --snapshot' }} --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GOPATH: ${{ needs.checks.outputs.go_path }}
@@ -256,24 +270,140 @@ jobs:
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
+ build-docker:
+ name: Build Docker OSS
+ needs: [binaries, checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian, alpine]
+ platforms:
+ ["linux/arm, linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"]
+ include:
+ - image: ubi
+ platforms: "linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"
+ uses: ./.github/workflows/build-oss.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
+ docs-only: ${{ needs.checks.outputs.docs_only == 'true' }}
+ tag: ${{ needs.checks.outputs.build_tag }}
+ branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ permissions:
+ contents: read
+ actions: read
+ security-events: write
+ id-token: write
+ packages: write
+ secrets: inherit
+
+ build-docker-plus:
+ name: Build Docker Plus
+ needs: [binaries, checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian-plus, alpine-plus, alpine-plus-fips]
+ platforms: ["linux/arm64, linux/amd64"]
+ target: [goreleaser, aws]
+ include:
+ - image: ubi-plus
+ platforms: "linux/arm64, linux/amd64, linux/s390x"
+ target: goreleaser
+ uses: ./.github/workflows/build-plus.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ target: ${{ matrix.target }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ tag: ${{ needs.checks.outputs.build_tag }}
+ forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
+ docs-only: ${{ needs.checks.outputs.docs_only == 'true' }}
+ permissions:
+ contents: read
+ security-events: write
+ id-token: write
+ secrets: inherit
+
+ build-docker-nap:
+ name: Build Docker NAP
+ needs: [binaries, checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian-plus-nap]
+ platforms: ["linux/amd64"]
+ target: [goreleaser, aws]
+ nap_modules: [dos, waf, "waf,dos"]
+ include:
+ - image: ubi-9-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: dos
+ - image: ubi-8-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: "waf,dos"
+ - image: ubi-9-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: dos
+ - image: ubi-8-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: "waf,dos"
+ - image: alpine-plus-nap-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ uses: ./.github/workflows/build-plus.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ target: ${{ matrix.target }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ tag: ${{ needs.checks.outputs.build_tag }}
+ nap-modules: ${{ matrix.nap_modules }}
+ forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
+ docs-only: ${{ needs.checks.outputs.docs_only == 'true' }}
+ permissions:
+ contents: read
+ security-events: write
+ id-token: write
+ secrets: inherit
+
helm-tests:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Helm Tests ${{ matrix.base-os }}
runs-on: ubuntu-22.04
- needs: [checks, binaries]
+ needs: [checks, binaries, build-docker, build-docker-plus]
strategy:
+ fail-fast: false
matrix:
include:
- base-os: debian
image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
tag: ${{ needs.checks.outputs.build_tag }}
type: oss
- platforms: "linux/arm, linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"
- base-os: debian-plus
image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-plus-ingress
tag: ${{ needs.checks.outputs.build_tag }}
type: plus
- platforms: "linux/arm64, linux/amd64"
permissions:
contents: read
id-token: write
@@ -281,21 +411,6 @@ jobs:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- - name: Fetch Cached Artifacts
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
-
- - name: Docker Buildx
- uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
-
- - name: Setup QEMU
- uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
- with:
- platforms: ${{ matrix.platforms }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
-
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
@@ -303,7 +418,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -311,61 +426,58 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
- - name: Check if base images exist
- id: base_exists
+ - name: Check if stable image exists
+ id: stable_exists
run: |
- if docker manifest inspect gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.base-os }}; then
+ if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Pull build image
+ run: |
+ docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
+ if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 0 }}
- - name: Build Base Container
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
+ - name: Fetch Cached Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
- file: build/Dockerfile
- context: "."
- cache-from: type=gha,scope=${{ matrix.base-os }}
- cache-to: type=gha,scope=${{ matrix.base-os }},mode=max
- target: common
- tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.base-os }}
- platforms: ${{ matrix.platforms }}
- pull: true
- push: true
- build-args: |
- BUILD_OS=${{ matrix.base-os }}
- IC_VERSION=${{ needs.checks.outputs.ic_version }}
- secrets: |
- ${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
- ${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.base_exists.outputs.exists != 0 }}
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Docker Buildx
+ uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Build Docker Image ${{ matrix.base-os }}
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.base-os }}
- target: goreleaser${{ needs.checks.outputs.forked_workflow == 'false' && '-prebuilt' || '' }}
+ target: goreleaser
tags: "${{ matrix.image }}:${{ matrix.tag }}"
pull: true
load: true
build-args: |
BUILD_OS=${{ matrix.base-os }}
- PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.base-os }}
IC_VERSION=CI
secrets: |
${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Deploy Kubernetes
id: k8s
run: |
kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
- kind load docker-image ${{ matrix.image }}:${{ matrix.tag }} --name ${{ github.run_id }}
+ kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
+ if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
- name: Install Chart
run: >
@@ -379,10 +491,12 @@ jobs:
--set controller.telemetryReporting.enable=false
--wait
working-directory: ${{ github.workspace }}/charts/nginx-ingress
+ if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
- name: Expose Test Ingresses
run: |
kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
+ if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
- name: Test HTTP
run: |
@@ -394,6 +508,7 @@ jobs:
fi
printf '.'; counter=$(($counter+1)); sleep 5;
done
+ if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
- name: Test HTTPS
run: |
@@ -405,6 +520,7 @@ jobs:
fi
printf '.'; counter=$(($counter+1)); sleep 5;
done
+ if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
setup-matrix:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
@@ -422,11 +538,7 @@ jobs:
- id: set-matrix
run: |
- if [ "${{ github.event_name }}" == "schedule" ]; then
- echo "matrix=$(cat .github/data/matrix-regression.json | jq -c --argjson latest '${{ needs.checks.outputs.latest_kindest_node_versions }}' '.k8s += $latest')" >> $GITHUB_OUTPUT
- else
- echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
- fi
+ echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
- name: Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
@@ -438,7 +550,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -446,18 +558,18 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Check if test image exists
id: check-image
run: |
- docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}
shell: bash
continue-on-error: true
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Build Test-Runner Container
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: tests/Dockerfile
context: "."
@@ -466,13 +578,13 @@ jobs:
pull: true
push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
load: false
- if: ${{ steps.check-image.outcome == 'failure' }}
+ if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
smoke-tests:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
runs-on: ubuntu-22.04
- needs: [checks, setup-matrix]
+ needs: [checks, setup-matrix, build-docker, build-docker-plus, build-docker-nap]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
@@ -490,15 +602,6 @@ jobs:
echo "build_tag=${{ needs.checks.outputs.build_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
echo "stable_tag=${{ needs.checks.outputs.stable_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
- - name: NAP modules
- id: nap_modules
- run: |
- [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || name="${{ matrix.images.nap_modules }}"
- [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="both" || modules="${{ matrix.images.nap_modules }}"
- echo "modules=${modules}" >> $GITHUB_OUTPUT
- echo "name=${name}" >> $GITHUB_OUTPUT
- if: ${{ matrix.images.nap_modules }}
-
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
@@ -506,7 +609,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -514,47 +617,29 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- - name: Check if base images exist
- id: base_exists
+ - name: Check if stable image exists
+ id: stable_exists
run: |
- if docker manifest inspect gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.images.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }}; then
+ if docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.stable_tag }}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
-
- - name: Docker Buildx
- uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- - name: Setup QEMU
- uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
- with:
- platforms: ${{ matrix.platforms }}
+ - name: NAP modules
+ id: nap_modules
+ run: |
+ [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || modules="${{ matrix.images.nap_modules }}"
+ echo "modules=${modules}" >> $GITHUB_OUTPUT
+ if: ${{ matrix.images.nap_modules }}
- - name: Build Base Container
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
- with:
- file: build/Dockerfile
- context: "."
- cache-from: type=gha,scope=${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }}
- cache-to: type=gha,scope=${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
- target: common
- tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.images.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }}
- platforms: ${{ matrix.images.platforms }}
- pull: true
- push: true
- build-args: |
- BUILD_OS=${{ matrix.images.image }}
- IC_VERSION=${{ needs.checks.outputs.ic_version }}
- ${{ steps.nap_modules.outputs.modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
- secrets: |
- ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
- ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
- ${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.base_exists.outputs.exists != 0 }}
+ - name: Pull build image
+ run: |
+ docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
@@ -562,6 +647,7 @@ jobs:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
fail-on-cache-miss: true
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Check if test image exists
id: check-image
@@ -569,10 +655,10 @@ jobs:
docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
shell: bash
continue-on-error: true
- if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Build Test-Runner Container
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: tests/Dockerfile
context: "."
@@ -581,29 +667,29 @@ jobs:
pull: true
push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
load: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- if: ${{ needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' }}
+ if: ${{ ( needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' ) && needs.checks.outputs.docs_only == 'false' }}
- name: Build ${{ matrix.images.image }} Container
- uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
cache-to: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
- target: goreleaser${{ needs.checks.outputs.forked_workflow == 'false' && '-prebuilt' || '' }}
+ target: goreleaser
tags: "${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}"
load: true
pull: true
build-args: |
BUILD_OS=${{ matrix.images.image }}
IC_VERSION=CI
- PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.images.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
${{ contains(matrix.images.image, 'nap') && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
${{ contains(matrix.images.marker, 'appprotect') && 'DEBIAN_VERSION=buster-slim' || '' }}
secrets: |
${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Run Smoke Tests
id: smoke-tests
@@ -616,6 +702,7 @@ jobs:
k8s-version: ${{ matrix.k8s }}
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
- name: Upload Test Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
@@ -638,179 +725,16 @@ jobs:
exit 1
fi
- build-docker:
- if: ${{ needs.checks.outputs.docs_only != 'true' }}
- name: Build Docker OSS
+ tag-stable:
+ name: Tag tested image as stable
needs: [checks, smoke-results]
- strategy:
- fail-fast: false
- matrix:
- image: [debian, alpine]
- platforms:
- ["linux/arm, linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"]
- include:
- - image: ubi
- platforms: "linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"
- uses: ./.github/workflows/build-oss.yml
- with:
- platforms: ${{ matrix.platforms }}
- image: ${{ matrix.image }}
- go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- publish-image: ${{ needs.checks.outputs.publish_images == 'true' }}
- base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- permissions:
- contents: read
- actions: read
- security-events: write
- id-token: write
- packages: write
- secrets: inherit
-
- build-docker-plus:
- if: ${{ needs.checks.outputs.docs_only != 'true' }}
- name: Build Docker Plus
- needs: [checks, smoke-results, release-notes]
- strategy:
- fail-fast: false
- matrix:
- image: [debian-plus, alpine-plus, alpine-plus-fips]
- platforms: ["linux/arm64, linux/amd64"]
- target: [goreleaser, aws]
- include:
- - image: ubi-plus
- platforms: "linux/arm64, linux/amd64, linux/s390x"
- target: goreleaser
- uses: ./.github/workflows/build-plus.yml
- with:
- platforms: ${{ matrix.platforms }}
- image: ${{ matrix.image }}
- target: ${{ matrix.target }}
- go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- release-url: ${{ needs.release-notes.outputs.release-url }}
- publish-image: ${{ needs.checks.outputs.publish_images == 'true' }}
- publish-aws-market-place: ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/heads/release-') && contains(matrix.target, 'aws') }}
- publish-nginx-reqistry: ${{ needs.checks.outputs.publish_images == 'true' && ! contains(matrix.target, 'aws') }}
- forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- permissions:
- contents: read
- security-events: write
- id-token: write
- secrets: inherit
-
- build-docker-nap:
- if: ${{ needs.checks.outputs.docs_only != 'true' }}
- name: Build Docker NAP
- needs: [checks, smoke-results, release-notes]
- strategy:
- fail-fast: false
- matrix:
- image: [debian-plus-nap]
- platforms: ["linux/amd64"]
- target: [goreleaser, aws]
- nap_modules: [dos, waf, "waf,dos"]
- include:
- - image: ubi-9-plus-nap
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- - image: ubi-8-plus-nap
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: dos
- - image: ubi-8-plus-nap
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: "waf,dos"
- - image: ubi-9-plus-nap
- target: aws
- platforms: "linux/amd64"
- nap_modules: waf
- - image: ubi-8-plus-nap
- target: aws
- platforms: "linux/amd64"
- nap_modules: dos
- - image: ubi-8-plus-nap
- target: aws
- platforms: "linux/amd64"
- nap_modules: "waf,dos"
- - image: alpine-plus-nap-fips
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- uses: ./.github/workflows/build-plus.yml
- with:
- platforms: ${{ matrix.platforms }}
- image: ${{ matrix.image }}
- target: ${{ matrix.target }}
- go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- nap_modules: ${{ matrix.nap_modules }}
- release-url: ${{ needs.release-notes.outputs.release-url }}
- publish-image: ${{ needs.checks.outputs.publish_images == 'true' }}
- publish-aws-market-place: ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/heads/release-') && contains(matrix.target, 'aws') }}
- publish-nginx-reqistry: ${{ needs.checks.outputs.publish_images == 'true' && ! contains(matrix.target, 'aws') }}
- forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
permissions:
- contents: read
- security-events: write
- id-token: write
- secrets: inherit
-
- publish-helm:
- name: Package and Publish Helm Chart
- needs: [checks, helm-tests]
- if: ${{ github.event_name == 'push' && ! startsWith(github.ref, 'refs/heads/release-') }}
- permissions:
- contents: write # for pushing to Helm Charts repository
- packages: write # for helm to push to GHCR
- uses: ./.github/workflows/publish-helm.yml
+ contents: read # To checkout repository
+ id-token: write # To sign into Google Container Registry
+ uses: ./.github/workflows/retag-images.yml
with:
- branch: ${{ github.ref_name }}
- ic_version: ${{ github.ref_type == 'tag' && needs.checks.outputs.ic_version || 'edge' }}
- chart_version: ${{ github.ref_type == 'tag' && needs.checks.outputs.chart_version || '0.0.0-edge' }}
- nginx_helm_repo: ${{ github.ref_type == 'tag' }}
+ source_tag: ${{ needs.checks.outputs.build_tag }}
+ target_tag: ${{ needs.checks.outputs.stable_tag }}
+ dry_run: false
secrets: inherit
-
- operator:
- name: Trigger PR for Operator
- runs-on: ubuntu-22.04
- needs: [checks, publish-helm]
- steps:
- - name:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
- with:
- github-token: ${{ secrets.NGINX_PAT }}
- script: |
- await github.rest.actions.createWorkflowDispatch({
- owner: context.repo.owner,
- repo: 'nginx-ingress-helm-operator',
- workflow_id: 'sync-chart.yml',
- ref: 'main',
- inputs: {
- chart_version: '${{ needs.checks.outputs.chart_version }}'
- },
- })
- if: github.ref_type == 'tag'
-
- gcp-marketplace:
- name: Trigger PR for GCP Marketplace
- runs-on: ubuntu-22.04
- needs: [checks, build-docker-plus, build-docker-nap]
- steps:
- - name:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
- with:
- github-token: ${{ secrets.NGINX_PAT }}
- script: |
- await github.rest.actions.createWorkflowDispatch({
- owner: context.repo.owner,
- repo: 'kubernetes-ingress-gcp',
- workflow_id: 'sync-chart.yml',
- ref: 'main',
- inputs: {
- chart_version: '${{ needs.checks.outputs.chart_version }}'
- },
- })
- if: github.ref_type == 'tag'
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 0 && needs.checks.outputs.docs_only == 'false' }}
diff --git a/.github/workflows/create-release-tag.yml b/.github/workflows/create-release-tag.yml
deleted file mode 100644
index 9b1ce39b07..0000000000
--- a/.github/workflows/create-release-tag.yml
+++ /dev/null
@@ -1,56 +0,0 @@
-name: "Create Tag on release branch"
-
-on:
- workflow_dispatch:
- inputs:
- release_branch:
- required: true
- type: string
- default: 'release-0.0'
- tag:
- required: false
- type: string
- default: 'vx.x.x'
- dry_run:
- type: boolean
- default: false
-
-
-defaults:
- run:
- shell: bash
-
-permissions:
- contents: read
-
-jobs:
- create:
- name: Create Tag on release branch in NIC repo
- runs-on: ubuntu-latest
- permissions:
- contents: write
- steps:
- - name: Checkout NIC repo
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- ref: ${{ inputs.release_branch }}
-
- - name: Create new release Tag
- run: |
- branch="${{ inputs.release_branch }}"
- tag="${{ inputs.tag }}"
- if git rev-parse --verify refs/tags/${tag}; then
- echo "Adding tag ${tag}."
- git tag -a ${tag} -m "Version ${tag#v*}"
- echo "Pushing to tag ${tag} to branch ${branch}"
- if ! ${{ inputs.dry_run }}; then
- git push origin "${tag}"
- else
- echo "DRY RUN not making any changes"
- git push --dry-run origin "${tag}"
- fi
- else
- echo "Warning: Tag ${tag} already exists. Not making any changes"
- fi
- env:
- GITHUB_TOKEN: ${{ secrets.NGINX_PAT }}
diff --git a/.github/workflows/edge.yml b/.github/workflows/edge.yml
new file mode 100644
index 0000000000..f12e97a127
--- /dev/null
+++ b/.github/workflows/edge.yml
@@ -0,0 +1,303 @@
+on:
+ pull_request:
+ branches:
+ - main
+ types:
+ - closed
+
+defaults:
+ run:
+ shell: bash
+
+concurrency:
+ group: ${{ github.ref_name }}-edge
+ cancel-in-progress: true
+
+permissions:
+ contents: read
+
+jobs:
+ checks:
+ name: Checks and variables
+ if: github.event.pull_request.merged == true
+ runs-on: ubuntu-22.04
+ permissions:
+ contents: read
+ id-token: write
+ outputs:
+ go_path: ${{ steps.vars.outputs.go_path }}
+ go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
+ binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
+ chart_version: ${{ steps.vars.outputs.chart_version }}
+ ic_version: ${{ steps.vars.outputs.ic_version }}
+ docker_md5: ${{ steps.vars.outputs.docker_md5 }}
+ build_tag: ${{ steps.vars.outputs.build_tag }}
+ stable_tag: ${{ steps.vars.outputs.stable_tag }}
+ stable_image_exists: ${{ steps.stable_exists.outputs.exists }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+
+ - name: Setup Golang Environment
+ uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
+ with:
+ go-version-file: go.mod
+
+ - name: Output Variables
+ id: vars
+ run: |
+ echo "go_path=$(go env GOPATH)" >> $GITHUB_OUTPUT
+ source .github/data/version.txt
+ echo "ic_version=${IC_VERSION}" >> $GITHUB_OUTPUT
+ echo "chart_version=${HELM_CHART_VERSION}" >> $GITHUB_OUTPUT
+ ./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
+ ./.github/scripts/variables.sh docker_md5 >> $GITHUB_OUTPUT
+ ./.github/scripts/variables.sh build_tag >> $GITHUB_OUTPUT
+ ./.github/scripts/variables.sh stable_tag >> $GITHUB_OUTPUT
+ cat $GITHUB_OUTPUT
+
+ - name: Fetch Cached Binary Artifacts
+ id: binary-cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ steps.vars.outputs.go_code_md5 }}
+ lookup-only: true
+
+ - name: Authenticate to Google Cloud
+ id: auth
+ uses: google-github-actions/auth@55bd3a7c6e2ae7cf1877fd1ccb9d54c0503c457c # v2.1.2
+ with:
+ token_format: access_token
+ workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+
+ - name: Login to GCR
+ uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
+ with:
+ registry: gcr.io
+ username: oauth2accesstoken
+ password: ${{ steps.auth.outputs.access_token }}
+
+ - name: Check if stable image exists
+ id: stable_exists
+ run: |
+ if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress:${{ steps.vars.outputs.stable_tag }}; then
+ echo "exists=0" >> $GITHUB_OUTPUT
+ else
+ echo "exists=1" >> $GITHUB_OUTPUT
+ fi
+
+ build-docker:
+ if: ${{ needs.checks.outputs.stable_image_exists != 'true' }}
+ name: Build Docker OSS
+ needs: [checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian, alpine]
+ platforms:
+ ["linux/arm, linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"]
+ include:
+ - image: ubi
+ platforms: "linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"
+ uses: ./.github/workflows/build-oss.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ forked-workflow: false
+ docs-only: false
+ tag: ${{ needs.checks.outputs.build_tag }}
+ branch: ${{ github.ref }}
+ permissions:
+ contents: read
+ actions: read
+ security-events: write
+ id-token: write
+ packages: write
+ secrets: inherit
+
+ build-docker-plus:
+ if: ${{ needs.checks.outputs.stable_image_exists != 'true' }}
+ name: Build Docker Plus
+ needs: [checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian-plus, alpine-plus, alpine-plus-fips]
+ platforms: ["linux/arm64, linux/amd64"]
+ target: [goreleaser, aws]
+ include:
+ - image: ubi-plus
+ platforms: "linux/arm64, linux/amd64, linux/s390x"
+ target: goreleaser
+ uses: ./.github/workflows/build-plus.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ target: ${{ matrix.target }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ forked-workflow: false
+ docs-only: false
+ tag: ${{ needs.checks.outputs.build_tag }}
+ branch: ${{ github.ref }}
+ permissions:
+ contents: read
+ security-events: write
+ id-token: write
+ secrets: inherit
+
+ build-docker-nap:
+ if: ${{ needs.checks.outputs.stable_image_exists != 'true' }}
+ name: Build Docker NAP
+ needs: [checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian-plus-nap]
+ platforms: ["linux/amd64"]
+ target: [goreleaser, aws]
+ nap_modules: [dos, waf, "waf,dos"]
+ include:
+ - image: ubi-9-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: dos
+ - image: ubi-8-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: "waf,dos"
+ - image: ubi-9-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: dos
+ - image: ubi-8-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: "waf,dos"
+ - image: alpine-plus-nap-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ uses: ./.github/workflows/build-plus.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ target: ${{ matrix.target }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ nap-modules: ${{ matrix.nap_modules }}
+ forked-workflow: false
+ docs-only: false
+ tag: ${{ needs.checks.outputs.build_tag }}
+ branch: ${{ github.ref }}
+ permissions:
+ contents: read
+ security-events: write
+ id-token: write
+ secrets: inherit
+
+ tag-stable:
+ if: ${{ needs.checks.outputs.stable_image_exists != 'true' }}
+ name: Tag build image as stable
+ needs: [checks, build-docker, build-docker-plus, build-docker-nap]
+ permissions:
+ contents: read # To checkout repository
+ id-token: write # To sign into Google Container Registry
+ uses: ./.github/workflows/retag-images.yml
+ with:
+ source_tag: ${{ needs.checks.outputs.build_tag }}
+ target_tag: ${{ needs.checks.outputs.stable_tag }}
+ dry_run: false
+ secrets: inherit
+
+ tag-edge:
+ name: Tag tested image as stable
+ needs: [checks, build-docker, build-docker-plus, build-docker-nap]
+ permissions:
+ contents: read # To checkout repository
+ id-token: write # To sign into Google Container Registry
+ uses: ./.github/workflows/retag-images.yml
+ with:
+ source_tag: ${{ needs.checks.outputs.stable_tag }}
+ target_tag: "edge"
+ dry_run: false
+ secrets: inherit
+
+ release-oss:
+ name: Release Docker OSS
+ needs: [checks, build-docker]
+ uses: ./.github/workflows/oss-release.yml
+ with:
+ gcr_release_registry: false
+ ecr_public_registry: true
+ dockerhub_public_registry: true
+ quay_public_registry: true
+ github_public_registry: true
+ source_tag: ${{ needs.checks.outputs.stable_tag }}
+ target_tag: "edge"
+ dry_run: false
+ permissions:
+ contents: read
+ id-token: write
+ packages: write
+ secrets: inherit
+
+ release-plus:
+ name: Release Docker Plus
+ needs: [checks, build-docker-plus, build-docker-nap ]
+ uses: ./.github/workflows/plus-release.yml
+ with:
+ nginx_registry: true
+ gcr_release_registry: false
+ gcr_mktpl_registry: false
+ ecr_mktpl_registry: false
+ az_mktpl_registry: false
+ source_tag: ${{ needs.checks.outputs.stable_tag }}
+ target_tag: "edge"
+ dry_run: false
+ permissions:
+ contents: read
+ id-token: write
+ secrets: inherit
+
+ publish-helm-chart:
+ name: Publish Helm Chart
+ needs: [checks ]
+ uses: ./.github/workflows/publish-helm.yml
+ with:
+ branch: ${{ github.ref_name }}
+ ic_version: 0.0.0-edge
+ chart_version: edge
+ nginx_helm_repo: false
+ permissions:
+ contents: write # for pushing to Helm Charts repository
+ packages: write # for helm to push to GHCR
+ secrets: inherit
+
+ certify-openshift-images:
+ name: Certify OpenShift UBI images
+ runs-on: ubuntu-22.04
+ needs: [release-oss]
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ - name: Certify UBI OSS images in quay
+ uses: ./.github/actions/certify-openshift-image
+ continue-on-error: true
+ with:
+ image: quay.io/nginx/nginx-ingress:edge-ubi
+ project_id: ${{ secrets.CERTIFICATION_PROJECT_ID }}
+ pyxis_token: ${{ secrets.PYXIS_API_TOKEN }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000000..0c4112e54f
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,297 @@
+name: Release NIC
+
+on:
+ workflow_dispatch:
+ inputs:
+ nic_version:
+ description: "Version to release"
+ required: true
+ type: string
+ chart_version:
+ description: "Helm Chart version to release"
+ required: false
+ type: string
+ cnab_version:
+ description: "CNAB version for Azure Marketplace"
+ required: false
+ type: string
+ release_branch:
+ description: "Branch to release from"
+ required: true
+ type: string
+ dry_run:
+ description: "Dry Run?"
+ type: boolean
+ default: false
+
+defaults:
+ run:
+ shell: bash
+
+permissions:
+ contents: read
+
+jobs:
+ variables:
+ name: Set Variables
+ runs-on: ubuntu-22.04
+ permissions:
+ contents: read
+ outputs:
+ stable_tag: ${{ steps.vars.outputs.stable_tag }}
+ short_tag: ${{ steps.vars.outputs.short_tag }}
+ go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ fetch-depth: 0
+ ref: ${{ inputs.release_branch }}
+
+ - name: Output Variables
+ id: vars
+ run: |
+ ./.github/scripts/variables.sh stable_tag >> $GITHUB_OUTPUT
+ tag=${{ inputs.nic_version }}
+ echo "short_tag=${tag%.*}" >> $GITHUB_OUTPUT
+ ./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
+ cat $GITHUB_OUTPUT
+
+ tag:
+ name: Create Tag on release branch in NIC repo
+ runs-on: ubuntu-22.04
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout NIC repo
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ ref: ${{ inputs.release_branch }}
+
+ - name: Create new release Tag
+ run: |
+ branch="${{ inputs.release_branch }}"
+ tag="v${{ inputs.nic_version }}"
+ if git rev-parse --verify refs/tags/${tag}; then
+ echo "Adding tag ${tag}."
+ git tag -a ${tag} -m "Version ${tag#v*}"
+ echo "Pushing to tag ${tag} to branch ${branch}"
+ if ! ${{ inputs.dry_run }}; then
+ git push origin "${tag}"
+ else
+ echo "DRY RUN not making any changes"
+ git push --dry-run origin "${tag}"
+ fi
+ else
+ echo "Warning: Tag ${tag} already exists. Not making any changes"
+ fi
+ env:
+ GITHUB_TOKEN: ${{ secrets.NGINX_PAT }}
+
+ release-oss:
+ name: Release Docker OSS
+ needs: [variables]
+ uses: ./.github/workflows/oss-release.yml
+ with:
+ gcr_release_registry: false
+ ecr_public_registry: true
+ dockerhub_public_registry: true
+ quay_public_registry: true
+ github_public_registry: true
+ source_tag: ${{ needs.variables.outputs.stable_tag }}
+ target_tag: ${{ inputs.nic_version }}
+ short_target_tag: ${{ needs.variables.outputs.short_tag }}
+ dry_run: ${{ inputs.dry_run }}
+ permissions:
+ contents: read
+ id-token: write
+ packages: write
+ secrets: inherit
+
+ release-plus:
+ name: Release Docker Plus
+ needs: [variables]
+ uses: ./.github/workflows/plus-release.yml
+ with:
+ nginx_registry: true
+ gcr_release_registry: true
+ gcr_mktpl_registry: true
+ ecr_mktpl_registry: true
+ az_mktpl_registry: true
+ source_tag: ${{ needs.variables.outputs.stable_tag }}
+ target_tag: ${{ inputs.nic_version }}
+ short_target_tag: ${{ needs.variables.outputs.short_tag }}
+ dry_run: ${{ inputs.dry_run }}
+ permissions:
+ contents: read
+ id-token: write
+ secrets: inherit
+
+ publish-helm-chart:
+ if: ${{ ! inputs.dry_run }}
+ name: Publish Helm Chart
+ uses: ./.github/workflows/publish-helm.yml
+ with:
+ branch: ${{ inputs.release_branch }}
+ ic_version: ${{ inputs.nic_version }}
+ chart_version: ${{ inputs.chart_version }}
+ nginx_helm_repo: true
+ permissions:
+ contents: write # for pushing to Helm Charts repository
+ packages: write # for helm to push to GHCR
+ secrets: inherit
+
+ certify-openshift-images:
+ if: ${{ ! inputs.dry_run }}
+ name: Certify OpenShift UBI images
+ runs-on: ubuntu-22.04
+ needs: [release-oss]
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ ref: ${{ inputs.release_branch }}
+
+ - name: Certify UBI OSS images in quay
+ uses: ./.github/actions/certify-openshift-image
+ continue-on-error: true
+ with:
+ image: quay.io/nginx/nginx-ingress:${{ inputs.nic_version }}-ubi
+ project_id: ${{ secrets.CERTIFICATION_PROJECT_ID }}
+ pyxis_token: ${{ secrets.PYXIS_API_TOKEN }}
+
+ operator:
+ if: ${{ ! inputs.dry_run }}
+ name: Trigger PR for Operator
+ runs-on: ubuntu-22.04
+ needs: [publish-helm-chart]
+ steps:
+ - name:
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
+ with:
+ github-token: ${{ secrets.NGINX_PAT }}
+ script: |
+ await github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: 'nginx-ingress-helm-operator',
+ workflow_id: 'sync-chart.yml',
+ ref: 'main',
+ inputs: {
+ chart_version: '${{ inputs.chart_version }}'
+ },
+ })
+
+ gcp-marketplace:
+ if: ${{ ! inputs.dry_run }}
+ name: Trigger PR for GCP Marketplace
+ runs-on: ubuntu-22.04
+ needs: [publish-helm-chart]
+ steps:
+ - name:
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
+ with:
+ github-token: ${{ secrets.NGINX_PAT }}
+ script: |
+ await github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: 'kubernetes-ingress-gcp',
+ workflow_id: 'sync-chart.yml',
+ ref: 'main',
+ inputs: {
+ chart_version: '${{ inputs.chart_version }}'
+ },
+ })
+
+ azure-marketplace:
+ if: ${{ ! inputs.dry_run }}
+ name: Trigger CNAB Build for Azure Marketplace
+ runs-on: ubuntu-22.04
+ needs: [publish-helm-chart]
+ steps:
+ - name:
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
+ with:
+ github-token: ${{ secrets.NGINX_PAT }}
+ script: |
+ await github.rest.actions.createWorkflowDispatch({
+ owner: context.repo.owner,
+ repo: 'kubernetes-ingress-azure',
+ workflow_id: 'build-cnab.yml',
+ ref: 'main',
+ inputs: {
+ chart_version: '${{ inputs.chart_version }}'
+ ic_version: '${{ inputs.nic_version }}'
+ cnab_version: '${{ inputs.cnab_version }}'
+ },
+ })
+
+ aws-marketplace:
+ if: ${{ ! inputs.dry_run }}
+ name: Publish to AWS Marketplace
+ runs-on: ubuntu-22.04
+ needs: [release-plus]
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - image: 709825985650.dkr.ecr.us-east-1.amazonaws.com/nginx/nginx-plus-ingress:${{ inputs.nic_version }}-mktpl
+ product_id: AWS_PRODUCT_ID
+ - image: 709825985650.dkr.ecr.us-east-1.amazonaws.com/nginx/nginx-plus-ingress-nap:${{ inputs.nic_version }}-mktpl
+ product_id: AWS_NAP_WAF_PRODUCT_ID
+ - image: 709825985650.dkr.ecr.us-east-1.amazonaws.com/nginx/nginx-plus-ingress-dos:${{ inputs.nic_version }}-mktpl
+ product_id: AWS_NAP_DOS_PRODUCT_ID
+ - image: 709825985650.dkr.ecr.us-east-1.amazonaws.com/nginx/nginx-plus-ingress-dos-nap:${{ inputs.nic_version }}-mktpl
+ product_id: AWS_NAP_WAF_DOS_PRODUCT_ID
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ ref: ${{ inputs.release_branch }}
+
+ - name: Publish to AWS Marketplace
+ uses: nginxinc/aws-marketplace-publish@be512a7ae9666098bc4429a1afa27a11be6a3995 # v1.0.3
+ continue-on-error: true
+ with:
+ version: ${{ inputs.nic_version }}
+ product-id: ${{ secrets[matrix.product_id] }}
+ registry: ${{ matrix.image }}
+ release-notes: https://github.com/nginxinc/kubernetes-ingress/releases/tag/v${{ inputs.nic_version }}
+ description: |
+ Best-in-class traffic management solution for services in Amazon EKS.
+ This is the official implementation of NGINX Ingress Controller (based on NGINX Plus) from NGINX.
+ usage-instructions: |
+ This container requires Kubernetes and can be deployed to EKS.
+ Review the installation instructions https://docs.nginx.com/nginx-ingress-controller/installation/ and utilize the deployment resources available https://github.com/nginxinc/kubernetes-ingress/tree/v${{ inputs.nic_version }}/deployments
+ Use this image instead of building your own.
+
+ azure-upload:
+ name: Upload packages to Azure
+ runs-on: ubuntu-22.04
+ needs: [variables]
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ with:
+ ref: ${{ inputs.release_branch }}
+
+ - name: Fetch Cached Package Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
+ path: dist
+ fail-on-cache-miss: true
+
+ - name: Azure Login
+ uses: azure/login@8c334a195cbb38e46038007b304988d888bf676a # v2.0.0
+ with:
+ creds: ${{ secrets.AZURE_STORAGE_KEY }}
+
+ - name: Azure Upload Release Packages
+ uses: azure/CLI@965c8d7571d2231a54e321ddd07f7b10317f34d9 # v2.0.0
+ with:
+ inlineScript: |
+ for i in ./dist*; do
+ echo "Uploading ${i} to kubernetes-ingress/v${{ inputs.nic_version }}/${i##*/}"
+ az storage blob upload --auth-mode=login -f "$i" -c ${{ secrets.AZURE_BUCKET_NAME }} \
+ --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT }} --overwrite -n kubernetes-ingress/v${{ inputs.nic_version }}/${i##*/}
+ done
From 5c1de47af2728f5db5c91bdbaf0582d6cb236471 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Fri, 7 Jun 2024 09:13:50 +0100
Subject: [PATCH 02/38] testing azure upload
---
.github/scripts/create-release-tarballs.sh | 43 ++++++++
.github/workflows/azure-upload.yml | 122 +++++++++++++++++++--
2 files changed, 157 insertions(+), 8 deletions(-)
create mode 100755 .github/scripts/create-release-tarballs.sh
diff --git a/.github/scripts/create-release-tarballs.sh b/.github/scripts/create-release-tarballs.sh
new file mode 100755
index 0000000000..4954c4dfe5
--- /dev/null
+++ b/.github/scripts/create-release-tarballs.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+set -e
+
+directory=$1
+version=$2
+tarball_dir=${TARBALL_DIR:-tarballs}
+releases=$(find "${directory}" -mindepth 1 -type d)
+syft_binary=${SYFT_BIN:-"syft"}
+cosign_binary=${COSIGN_BIN:-"cosign"}
+
+if [ ! -d "${tarball_dir}" ]; then
+ mkdir "${tarball_dir}"
+fi
+
+for i in ${releases}; do
+ # fix for v1 in kubernetes-ingress_linux_amd64_v1
+ if [[ ${i} =~ v1 ]]; then
+ mv "${i}" "${i%*_v1}"
+ i=${i%*_v1}
+ fi
+
+ if [[ ${i} =~ aws ]]; then
+ continue
+ fi
+ product_name=$(basename "${i}" | cut -d '_' -f 1)
+ product_arch=$(echo "${i}" | cut -d '_' -f 2-)
+ product_release="${product_name}_${version}_${product_arch}"
+ # shellcheck disable=SC2086
+ tarball_name="${tarball_dir}/${product_release}.tar.gz"
+ cp -r "${i}" "${directory}/${product_release}"
+ cp README.md LICENSE CHANGELOG.md "${directory}/${product_release}"
+
+ tar -czf "${tarball_name}" "${directory}/${product_release}"
+ ${syft_binary} scan file:"${directory}/${product_release}/nginx-ingress" -o spdx-json > "${tarball_name}.spdx.json"
+ pushd "${tarball_dir}"
+ sha256sum "${product_release}.tar.gz" >> "${product_name}_${version}_checksums.txt"
+ sha256sum "${product_release}.tar.gz.spdx.json" >> "${product_name}_${version}_checksums.txt"
+ popd
+done
+
+checksum_file=$(ls "${tarball_dir}"/*_checksums.txt )
+${cosign_binary} sign-blob "${checksum_file}" --output-signature="${checksum_file}.sig" --output-certificate="${checksum_file}.pem" -y
diff --git a/.github/workflows/azure-upload.yml b/.github/workflows/azure-upload.yml
index b2d818233f..69a315b8cd 100644
--- a/.github/workflows/azure-upload.yml
+++ b/.github/workflows/azure-upload.yml
@@ -3,7 +3,7 @@ name: Upload NIC Release to Azure
on:
push:
branches:
- - image-build-refactor
+ - azure-upload
defaults:
run:
@@ -13,30 +13,136 @@ permissions:
contents: read
jobs:
+ variables:
+ name: Set Variables
+ runs-on: ubuntu-22.04
+ permissions:
+ contents: read
+ outputs:
+ go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
+ binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ fetch-depth: 0
+
+ - name: Output Variables
+ id: vars
+ run: |
+ ./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
+ cat $GITHUB_OUTPUT
+
+ - name: Fetch Cached Binary Artifacts
+ id: binary-cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ steps.vars.outputs.go_code_md5 }}
+ lookup-only: true
+
+ binaries:
+ name: Build Binaries
+ runs-on: ubuntu-22.04
+ needs: [variables]
+ permissions:
+ contents: write # for goreleaser/goreleaser-action to manage releases
+ id-token: write # for goreleaser/goreleaser-action to sign artifacts
+ issues: write # for goreleaser/goreleaser-action to close milestone
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ - name: Setup Golang Environment
+ uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
+ with:
+ go-version-file: go.mod
+ if: ${{ needs.variables.outputs.binary_cache_hit != 'true' }}
+
+ - name: Build binaries
+ uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
+ with:
+ version: latest
+ args: build --snapshot --clean
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ GOPATH: ${{ needs.checks.outputs.go_path }}
+ AWS_PRODUCT_CODE: ${{ secrets.AWS_PRODUCT_CODE }}
+ AWS_PUB_KEY: ${{ secrets.AWS_PUB_KEY }}
+ AWS_NAP_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_DOS_PRODUCT_CODE }}
+ AWS_NAP_DOS_PUB_KEY: ${{ secrets.AWS_NAP_DOS_PUB_KEY }}
+ AWS_NAP_WAF_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_PRODUCT_CODE }}
+ AWS_NAP_WAF_PUB_KEY: ${{ secrets.AWS_NAP_WAF_PUB_KEY }}
+ AWS_NAP_WAF_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_DOS_PRODUCT_CODE }}
+ AWS_NAP_WAF_DOS_PUB_KEY: ${{ secrets.AWS_NAP_WAF_DOS_PUB_KEY }}
+ GORELEASER_CURRENT_TAG: "v3.6.0"
+ if: ${{ needs.variables.outputs.binary_cache_hit != 'true' }}
+
+ - name: Fetch Binary Artifacts from Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
+ if: ${{ needs.variables.outputs.binary_cache_hit == 'true' }}
+
+ - name: Download Syft
+ id: syft
+ uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0
+
+ - name: Install Cosign
+ uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
+
+ - name: Create Tarballs
+ run: |
+ ./.github/scripts/create-release-tarballs.sh dist 3.6.0
+ ls -al tarballs
+ cat tarballs/kubernetes-ingress_3.6.0_checksums.txt
+ env:
+ SYFT_BIN: ${{ steps.syft.outputs.cmd }}
+
+ - name: Store Binary Artifacts in Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
+ if: ${{ needs.variables.outputs.binary_cache_hit != 'true' }}
+
+ - name: Store Tarball Artifacts in Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/tarballs
+ key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
+
azure-upload:
name: Upload packages to Azure
runs-on: ubuntu-22.04
+ needs: [variables, binaries]
+ permissions:
+ id-token: write
+ contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
- - name: Fetch Cached Package Artifacts
+ - name: Fetch Cached Tarball Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
- key: nginx-ingress-d2052fb01bb850127dd02aaaa6c790a9
- path: dist
+ key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
+ path: ${{ github.workspace }}/tarballs
fail-on-cache-miss: true
- - name: Azure Login
- uses: azure/login@8c334a195cbb38e46038007b304988d888bf676a # v2.0.0
+ - name: Azure login
+ uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
with:
- creds: ${{ secrets.AZURE_STORAGE_KEY }}
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Azure Upload Release Packages
uses: azure/CLI@965c8d7571d2231a54e321ddd07f7b10317f34d9 # v2.0.0
with:
inlineScript: |
- for i in ./dist*; do
+ for i in $(find tarballs -type f); do
echo "Uploading ${i} to kubernetes-ingress/v0.0.0/${i##*/}"
az storage blob upload --auth-mode=login -f "$i" -c ${{ secrets.AZURE_BUCKET_NAME }} \
--account-name ${{ secrets.AZURE_STORAGE_ACCOUNT }} --overwrite -n kubernetes-ingress/v0.0.0/${i##*/}
From 5415dcbb3ad185a1dcc9b826fc39d284510f82d2 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Wed, 12 Jun 2024 10:22:15 +0100
Subject: [PATCH 03/38] added dry_run to azure upload
---
.github/workflows/azure-upload.yml | 149 -----------------------------
.github/workflows/release.yml | 83 +++++++++++++---
2 files changed, 72 insertions(+), 160 deletions(-)
delete mode 100644 .github/workflows/azure-upload.yml
diff --git a/.github/workflows/azure-upload.yml b/.github/workflows/azure-upload.yml
deleted file mode 100644
index 69a315b8cd..0000000000
--- a/.github/workflows/azure-upload.yml
+++ /dev/null
@@ -1,149 +0,0 @@
-name: Upload NIC Release to Azure
-
-on:
- push:
- branches:
- - azure-upload
-
-defaults:
- run:
- shell: bash
-
-permissions:
- contents: read
-
-jobs:
- variables:
- name: Set Variables
- runs-on: ubuntu-22.04
- permissions:
- contents: read
- outputs:
- go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
- binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- fetch-depth: 0
-
- - name: Output Variables
- id: vars
- run: |
- ./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
- cat $GITHUB_OUTPUT
-
- - name: Fetch Cached Binary Artifacts
- id: binary-cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ steps.vars.outputs.go_code_md5 }}
- lookup-only: true
-
- binaries:
- name: Build Binaries
- runs-on: ubuntu-22.04
- needs: [variables]
- permissions:
- contents: write # for goreleaser/goreleaser-action to manage releases
- id-token: write # for goreleaser/goreleaser-action to sign artifacts
- issues: write # for goreleaser/goreleaser-action to close milestone
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- - name: Setup Golang Environment
- uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
- with:
- go-version-file: go.mod
- if: ${{ needs.variables.outputs.binary_cache_hit != 'true' }}
-
- - name: Build binaries
- uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
- with:
- version: latest
- args: build --snapshot --clean
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GOPATH: ${{ needs.checks.outputs.go_path }}
- AWS_PRODUCT_CODE: ${{ secrets.AWS_PRODUCT_CODE }}
- AWS_PUB_KEY: ${{ secrets.AWS_PUB_KEY }}
- AWS_NAP_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_DOS_PRODUCT_CODE }}
- AWS_NAP_DOS_PUB_KEY: ${{ secrets.AWS_NAP_DOS_PUB_KEY }}
- AWS_NAP_WAF_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_PRODUCT_CODE }}
- AWS_NAP_WAF_PUB_KEY: ${{ secrets.AWS_NAP_WAF_PUB_KEY }}
- AWS_NAP_WAF_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_DOS_PRODUCT_CODE }}
- AWS_NAP_WAF_DOS_PUB_KEY: ${{ secrets.AWS_NAP_WAF_DOS_PUB_KEY }}
- GORELEASER_CURRENT_TAG: "v3.6.0"
- if: ${{ needs.variables.outputs.binary_cache_hit != 'true' }}
-
- - name: Fetch Binary Artifacts from Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
- if: ${{ needs.variables.outputs.binary_cache_hit == 'true' }}
-
- - name: Download Syft
- id: syft
- uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0
-
- - name: Install Cosign
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
-
- - name: Create Tarballs
- run: |
- ./.github/scripts/create-release-tarballs.sh dist 3.6.0
- ls -al tarballs
- cat tarballs/kubernetes-ingress_3.6.0_checksums.txt
- env:
- SYFT_BIN: ${{ steps.syft.outputs.cmd }}
-
- - name: Store Binary Artifacts in Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
- if: ${{ needs.variables.outputs.binary_cache_hit != 'true' }}
-
- - name: Store Tarball Artifacts in Cache
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/tarballs
- key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
-
- azure-upload:
- name: Upload packages to Azure
- runs-on: ubuntu-22.04
- needs: [variables, binaries]
- permissions:
- id-token: write
- contents: read
- steps:
- - name: Checkout Repository
- uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
-
- - name: Fetch Cached Tarball Artifacts
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
- path: ${{ github.workspace }}/tarballs
- fail-on-cache-miss: true
-
- - name: Azure login
- uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
- with:
- client-id: ${{ secrets.AZURE_CLIENT_ID }}
- tenant-id: ${{ secrets.AZURE_TENANT_ID }}
- subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
-
- - name: Azure Upload Release Packages
- uses: azure/CLI@965c8d7571d2231a54e321ddd07f7b10317f34d9 # v2.0.0
- with:
- inlineScript: |
- for i in $(find tarballs -type f); do
- echo "Uploading ${i} to kubernetes-ingress/v0.0.0/${i##*/}"
- az storage blob upload --auth-mode=login -f "$i" -c ${{ secrets.AZURE_BUCKET_NAME }} \
- --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT }} --overwrite -n kubernetes-ingress/v0.0.0/${i##*/}
- done
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0c4112e54f..e460126784 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -41,6 +41,7 @@ jobs:
stable_tag: ${{ steps.vars.outputs.stable_tag }}
short_tag: ${{ steps.vars.outputs.short_tag }}
go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
+ binary_cache_sign_hit: ${{ steps.binary-cache-sign.outputs.cache-hit }}
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
@@ -57,6 +58,14 @@ jobs:
./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
+ - name: Fetch Cached Signed Binary Artifacts
+ id: binary-cache-sign
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/tarballs
+ key: nginx-ingress-release-${{ steps.vars.outputs.go_code_md5 }}
+ lookup-only: true
+
tag:
name: Create Tag on release branch in NIC repo
runs-on: ubuntu-22.04
@@ -264,34 +273,86 @@ jobs:
Review the installation instructions https://docs.nginx.com/nginx-ingress-controller/installation/ and utilize the deployment resources available https://github.com/nginxinc/kubernetes-ingress/tree/v${{ inputs.nic_version }}/deployments
Use this image instead of building your own.
+ binaries:
+ name: Process Binaries
+ runs-on: ubuntu-22.04
+ needs: [variables]
+ permissions:
+ contents: write # for goreleaser/goreleaser-action to manage releases
+ id-token: write # for goreleaser/goreleaser-action to sign artifacts
+ issues: write # for goreleaser/goreleaser-action to close milestone
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ - name: Fetch Binary Artifacts from Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
+ if: ${{ needs.variables.outputs.binary_cache_sign_hit != 'true' }}
+
+ - name: Download Syft
+ id: syft
+ uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0
+ if: ${{ needs.variables.outputs.binary_cache_sign_hit != 'true' }}
+
+ - name: Install Cosign
+ uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
+ if: ${{ needs.variables.outputs.binary_cache_sign_hit != 'true' }}
+
+ - name: Create Tarballs
+ run: |
+ ./.github/scripts/create-release-tarballs.sh dist ${{ inputs.nic_version }}
+ env:
+ SYFT_BIN: ${{ steps.syft.outputs.cmd }}
+ if: ${{ needs.variables.outputs.binary_cache_sign_hit != 'true' }}
+
+ - name: Store Tarball Artifacts in Cache
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/tarballs
+ key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
+ if: ${{ needs.variables.outputs.binary_cache_sign_hit != 'true' }}
+
azure-upload:
name: Upload packages to Azure
runs-on: ubuntu-22.04
- needs: [variables]
+ needs: [variables, binaries]
+ permissions:
+ id-token: write
+ contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
ref: ${{ inputs.release_branch }}
- - name: Fetch Cached Package Artifacts
+ - name: Fetch Cached Tarball Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
- key: nginx-ingress-${{ needs.variables.outputs.go_code_md5 }}
- path: dist
+ key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
+ path: ${{ github.workspace }}/tarballs
fail-on-cache-miss: true
- - name: Azure Login
- uses: azure/login@8c334a195cbb38e46038007b304988d888bf676a # v2.0.0
+ - name: Azure login
+ uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
with:
- creds: ${{ secrets.AZURE_STORAGE_KEY }}
+ client-id: ${{ secrets.AZURE_CLIENT_ID }}
+ tenant-id: ${{ secrets.AZURE_TENANT_ID }}
+ subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Azure Upload Release Packages
uses: azure/CLI@965c8d7571d2231a54e321ddd07f7b10317f34d9 # v2.0.0
with:
inlineScript: |
- for i in ./dist*; do
- echo "Uploading ${i} to kubernetes-ingress/v${{ inputs.nic_version }}/${i##*/}"
- az storage blob upload --auth-mode=login -f "$i" -c ${{ secrets.AZURE_BUCKET_NAME }} \
- --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT }} --overwrite -n kubernetes-ingress/v${{ inputs.nic_version }}/${i##*/}
+ for i in $(find tarballs -type f); do
+ echo -n "Uploading ${i} to kubernetes-ingress/v${{ inputs.nic_version }}/${i##*/} ... "
+ if ${{ ! inputs.dry_run}}; then
+ az storage blob upload --auth-mode=login -f "$i" -c ${{ secrets.AZURE_BUCKET_NAME }} \
+ --account-name ${{ secrets.AZURE_STORAGE_ACCOUNT }} --overwrite -n kubernetes-ingress/v${{ inputs.nic_version }}/${i##*/}
+ echo "done"
+ else
+ echo "skipped, dry_run."
+ fi
done
From e400a465c83b154b4cd63dafe9efddb47ec962a0 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Wed, 12 Jun 2024 10:30:56 +0100
Subject: [PATCH 04/38] remove excess permissions
---
.github/workflows/release.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e460126784..ff7f7df808 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -278,9 +278,7 @@ jobs:
runs-on: ubuntu-22.04
needs: [variables]
permissions:
- contents: write # for goreleaser/goreleaser-action to manage releases
- id-token: write # for goreleaser/goreleaser-action to sign artifacts
- issues: write # for goreleaser/goreleaser-action to close milestone
+ contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
From f35b132d1b5e18aa6d0ed5898756451e89644efd Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Wed, 12 Jun 2024 12:26:08 +0100
Subject: [PATCH 05/38] add github release to release workflow
---
.github/workflows/release.yml | 77 +++++++++++++++++++++++++++++++++++
1 file changed, 77 insertions(+)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ff7f7df808..94b3025157 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -354,3 +354,80 @@ jobs:
echo "skipped, dry_run."
fi
done
+
+ github-release:
+ name: Publish release to GitHub
+ runs-on: ubuntu-22.04
+ needs: [variables, binaries]
+ permissions:
+ contents: write # to modify the release
+ issues: write # to close milestone
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ with:
+ ref: ${{ inputs.release_branch }}
+
+ - name: Fetch Cached Tarball Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ key: nginx-ingress-release-${{ needs.variables.outputs.go_code_md5 }}
+ path: ${{ github.workspace }}/tarballs
+ fail-on-cache-miss: true
+
+ - name: Upload Release Assets
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ # clobber overwrites existing assets of the same name
+ run: |
+ if ! ${{ inputs.dry_run }}
+ gh release upload --clobber v${{ inputs.nic_version }} \
+ $(find ./tarballs -type f)
+ else
+ echo "Skipping adding binaries to Github Release, DRY_RUN"
+ fi
+
+ - name: Close Release Milestone
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ milestone_number=$(gh api \
+ -H "Accept: application/vnd.github.v3+json" \
+ /repos/${{ github.repository_owner }}/${{ github.repository }}/milestones \
+ | jq --arg version ${{ inputs.nic_version }} -r \
+ '.[] | select(.title == $version) | .number')
+ if ! ${{ inputs.dry_run }}
+ gh api --method PATCH -H "Accept: application/vnd.github.v3+json" \
+ /repos/${{ github.repository_owner }}/${{ github.repository }}/milestones/${milestone_number} \
+ else
+ echo "Skipping closing Github Release milestone, DRY_RUN"
+ fi
+
+ - name: Get Github release id
+ id: release-id
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ release_id=$(gh api \
+ -H "Accept: application/vnd.github.v3+json" \
+ -H "X-GitHub-Api-Version: 2022-11-28" \
+ /repos/${{ github.repository_owner }}/${{ github.repository }}/releases \
+ | jq --arg version ${{ inputs.nic_version }} -r \
+ '.[] | select(.name == $version) | .id')
+ echo "release_id=${release_id}" >> $GITHUB_OUTPUT
+
+ - name: Publish Github Release
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
+ with:
+ script: |
+ const {RELEASE_ID} = process.env
+ const release = (await github.rest.repos.updateRelease({
+ owner: context.payload.repository.owner.login,
+ repo: context.payload.repository.name,
+ release_id: `${RELEASE_ID}`,
+ draft: false,
+ }))
+ console.log(`Release published: ${release.data.html_url}`)
+ env:
+ RELEASE_ID: ${{ steps.release-id.outputs.release_id }}
+ if: ${{ ! inputs.dry_run }}
From 7c95c94929d684a30325143b4b6bb567df389476 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Wed, 12 Jun 2024 14:09:22 +0100
Subject: [PATCH 06/38] notify if release pipeline fails
---
.github/workflows/notifications.yml | 1 +
1 file changed, 1 insertion(+)
diff --git a/.github/workflows/notifications.yml b/.github/workflows/notifications.yml
index 16631422f4..ab7304833f 100644
--- a/.github/workflows/notifications.yml
+++ b/.github/workflows/notifications.yml
@@ -12,6 +12,7 @@ on:
- "OpenSSF Scorecards"
- "Build OSS"
- "Build Plus"
+ - "Release NIC"
types:
- completed
From c95231fba37cc77939b4449a42a0fc9ce8e26bef Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Thu, 13 Jun 2024 14:18:13 +0100
Subject: [PATCH 07/38] add slack notifications
---
.github/workflows/release.yml | 74 ++++++++++++++++++----
.github/workflows/updates-notification.yml | 5 +-
2 files changed, 66 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 94b3025157..c475efa18e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,6 +7,10 @@ on:
description: "Version to release"
required: true
type: string
+ source_tag:
+ description: "Source tag to release"
+ required: false
+ type: string
chart_version:
description: "Helm Chart version to release"
required: false
@@ -23,6 +27,11 @@ on:
description: "Dry Run?"
type: boolean
default: false
+ skip_step:
+ description: "Comma separated list of jobs to skip"
+ # publish-helm-chart,operator,aws-marketplace,azure-marketplace,gcp-marketplace,github-release,release-image-notification
+ type: string
+ required: false
defaults:
run:
@@ -38,7 +47,7 @@ jobs:
permissions:
contents: read
outputs:
- stable_tag: ${{ steps.vars.outputs.stable_tag }}
+ source_tag: ${{ steps.vars.outputs.stable_tag }}
short_tag: ${{ steps.vars.outputs.short_tag }}
go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
binary_cache_sign_hit: ${{ steps.binary-cache-sign.outputs.cache-hit }}
@@ -52,7 +61,11 @@ jobs:
- name: Output Variables
id: vars
run: |
- ./.github/scripts/variables.sh stable_tag >> $GITHUB_OUTPUT
+ if ${{ inputs.source_tag }}; then
+ echo "stable_tag=${{ inputs.source_tag }}" >> $GITHUB_OUTPUT
+ else
+ ./.github/scripts/variables.sh stable_tag >> $GITHUB_OUTPUT
+ fi
tag=${{ inputs.nic_version }}
echo "short_tag=${tag%.*}" >> $GITHUB_OUTPUT
./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
@@ -102,12 +115,12 @@ jobs:
needs: [variables]
uses: ./.github/workflows/oss-release.yml
with:
- gcr_release_registry: false
+ gcr_release_registry: true
ecr_public_registry: true
dockerhub_public_registry: true
quay_public_registry: true
github_public_registry: true
- source_tag: ${{ needs.variables.outputs.stable_tag }}
+ source_tag: ${{ needs.variables.outputs.source_tag }}
target_tag: ${{ inputs.nic_version }}
short_target_tag: ${{ needs.variables.outputs.short_tag }}
dry_run: ${{ inputs.dry_run }}
@@ -122,12 +135,12 @@ jobs:
needs: [variables]
uses: ./.github/workflows/plus-release.yml
with:
- nginx_registry: true
gcr_release_registry: true
+ nginx_registry: true
gcr_mktpl_registry: true
ecr_mktpl_registry: true
az_mktpl_registry: true
- source_tag: ${{ needs.variables.outputs.stable_tag }}
+ source_tag: ${{ needs.variables.outputs.source_tag }}
target_tag: ${{ inputs.nic_version }}
short_target_tag: ${{ needs.variables.outputs.short_tag }}
dry_run: ${{ inputs.dry_run }}
@@ -137,7 +150,7 @@ jobs:
secrets: inherit
publish-helm-chart:
- if: ${{ ! inputs.dry_run }}
+ if: ${{ ! inputs.dry_run && ! contains(inputs.skip_step, 'publish-helm-chart') }}
name: Publish Helm Chart
uses: ./.github/workflows/publish-helm.yml
with:
@@ -170,7 +183,7 @@ jobs:
pyxis_token: ${{ secrets.PYXIS_API_TOKEN }}
operator:
- if: ${{ ! inputs.dry_run }}
+ if: ${{ ! inputs.dry_run && ! contains(inputs.skip_step, 'operator') && !contains(inputs.skip_step, 'publish-helm-chart') }}
name: Trigger PR for Operator
runs-on: ubuntu-22.04
needs: [publish-helm-chart]
@@ -191,7 +204,7 @@ jobs:
})
gcp-marketplace:
- if: ${{ ! inputs.dry_run }}
+ if: ${{ ! inputs.dry_run && ! contains(inputs.skip_step, 'gcp-marketplace') }}
name: Trigger PR for GCP Marketplace
runs-on: ubuntu-22.04
needs: [publish-helm-chart]
@@ -212,7 +225,7 @@ jobs:
})
azure-marketplace:
- if: ${{ ! inputs.dry_run }}
+ if: ${{ ! inputs.dry_run && ! contains(inputs.skip_step, 'azure-marketplace') }}
name: Trigger CNAB Build for Azure Marketplace
runs-on: ubuntu-22.04
needs: [publish-helm-chart]
@@ -235,7 +248,7 @@ jobs:
})
aws-marketplace:
- if: ${{ ! inputs.dry_run }}
+ if: ${{ ! inputs.dry_run && ! contains(inputs.skip_step, 'aws-marketplace') }}
name: Publish to AWS Marketplace
runs-on: ubuntu-22.04
needs: [release-plus]
@@ -356,9 +369,10 @@ jobs:
done
github-release:
+ if: ${{ ! contains(inputs.skip_step, 'github-release') }}
name: Publish release to GitHub
runs-on: ubuntu-22.04
- needs: [variables, binaries]
+ needs: [variables, binaries, release-oss, release-plus]
permissions:
contents: write # to modify the release
issues: write # to close milestone
@@ -431,3 +445,39 @@ jobs:
env:
RELEASE_ID: ${{ steps.release-id.outputs.release_id }}
if: ${{ ! inputs.dry_run }}
+
+ release-image-notification:
+ if: ${{ ! inputs.dry_run && ! contains(inputs.skip_step, 'release-image-notification') }}
+ name: Notify Slack channels about image release
+ runs-on: ubuntu-22.04
+ needs: [variables, binaries, release-oss, release-plus]
+ permissions:
+ contents: read
+ actions: read
+ strategy:
+ fail-fast: false
+ matrix:
+ image: ["nginx/nginx-ingress:${{ inputs.nic_version }}", "nginx/nginx-ingress:${{ inputs.nic_version }}-ubi", "nginx/nginx-ingress:${{ inputs.nic_version }}-alpine"]
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
+ with:
+ ref: ${{ inputs.release_branch }}
+
+ - name: Get Image manifest digest
+ id: digest
+ run: |
+ digest=$(docker buildx imagetools inspect ${{ matrix.image }} --format '{{ json . }}' | jq -r .manifest.digest)
+
+ - name: Get Image tag
+ id: tag
+ run: |
+ tag=$(echo ${{ matrix.image }} | cut -d ':' -f 2)
+
+ - name: Notify Slack of Dockerhub image release
+ uses: ./.github/workflows/updates-notification.yml
+ with:
+ tag: ${{ steps.tag.outputs.tag }}
+ version: ${{ inputs.nic_version }}
+ image_digest: ${{ steps.digest.outputs.digest }}
+ slack_webhook_url: ${{ secrets.SLACK_WEBHOOK }}
diff --git a/.github/workflows/updates-notification.yml b/.github/workflows/updates-notification.yml
index 6168dbffef..102045956f 100644
--- a/.github/workflows/updates-notification.yml
+++ b/.github/workflows/updates-notification.yml
@@ -12,6 +12,9 @@ on:
image_digest:
required: true
type: string
+ slack_webhook_url:
+ required: true
+ type: string
defaults:
run:
@@ -79,4 +82,4 @@ jobs:
}]
}
env:
- SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
+ SLACK_WEBHOOK_URL: ${{ inputs.slack_webhook_url }}
From ea2d395f67ad9a6a554edc30114c4202ef19825f Mon Sep 17 00:00:00 2001
From: pasmant <78279234+pasmant@users.noreply.github.com>
Date: Wed, 12 Jun 2024 15:00:54 +0300
Subject: [PATCH 08/38] Fix test_dos_sec_logs_on (#5725)
---
tests/suite/test_dos.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/suite/test_dos.py b/tests/suite/test_dos.py
index beffdff497..3dfc93e995 100644
--- a/tests/suite/test_dos.py
+++ b/tests/suite/test_dos.py
@@ -209,7 +209,6 @@ def test_ap_nginx_config_entries(
for _ in conf_nginx_directive:
assert _ in nginx_config
- @pytest.mark.skip(reason="Intermittent failures while sending dos logs to syslog")
def test_dos_sec_logs_on(
self,
kube_apis,
@@ -239,6 +238,7 @@ def test_dos_sec_logs_on(
get_ingress_nginx_template_conf(kube_apis.v1, test_namespace, "dos-ingress", pod_name, "nginx-ingress")
print("----------------------- Send request ----------------------")
+ wait_before_test(5)
response = requests.get(dos_setup.req_url, headers={"host": "dos.example.com"}, verify=False)
print(response.text)
wait_before_test(10)
@@ -250,7 +250,7 @@ def test_dos_sec_logs_on(
print(log_contents)
retry = 0
- while 'product="app-protect-dos"' not in log_contents and retry < 10:
+ while 'product="app-protect-dos"' not in log_contents and retry < 20:
wait_before_test()
retry += 1
From bd93b6bd39f2443225b3be3003159473d2fe1d6f Mon Sep 17 00:00:00 2001
From: Venktesh Shivam Patel
Date: Wed, 12 Jun 2024 15:06:14 +0100
Subject: [PATCH 09/38] enable external service args (#5736)
---
deployments/daemon-set/nginx-ingress.yaml | 4 ++--
deployments/daemon-set/nginx-plus-ingress.yaml | 4 ++--
deployments/deployment/nginx-ingress.yaml | 4 ++--
deployments/deployment/nginx-plus-ingress.yaml | 4 ++--
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/deployments/daemon-set/nginx-ingress.yaml b/deployments/daemon-set/nginx-ingress.yaml
index 47ad7accd9..2f462e449f 100644
--- a/deployments/daemon-set/nginx-ingress.yaml
+++ b/deployments/daemon-set/nginx-ingress.yaml
@@ -88,11 +88,11 @@ spec:
fieldPath: metadata.name
args:
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
+ - -report-ingress-status
+ - -external-service=nginx-ingress
#- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
#- -include-year
#- -v=3 # Enables extensive logging. Useful for troubleshooting.
- #- -report-ingress-status
- #- -external-service=nginx-ingress
#- -enable-prometheus-metrics
#- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
# initContainers:
diff --git a/deployments/daemon-set/nginx-plus-ingress.yaml b/deployments/daemon-set/nginx-plus-ingress.yaml
index af3f5a8e33..a769154900 100644
--- a/deployments/daemon-set/nginx-plus-ingress.yaml
+++ b/deployments/daemon-set/nginx-plus-ingress.yaml
@@ -89,13 +89,13 @@ spec:
args:
- -nginx-plus
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
+ - -report-ingress-status
+ - -external-service=nginx-ingress
#- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
#- -include-year
#- -enable-app-protect
#- -enable-app-protect-dos
#- -v=3 # Enables extensive logging. Useful for troubleshooting.
- #- -report-ingress-status
- #- -external-service=nginx-ingress
#- -enable-prometheus-metrics
#- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
# initContainers:
diff --git a/deployments/deployment/nginx-ingress.yaml b/deployments/deployment/nginx-ingress.yaml
index f52cea9b7a..2a1469b812 100644
--- a/deployments/deployment/nginx-ingress.yaml
+++ b/deployments/deployment/nginx-ingress.yaml
@@ -87,13 +87,13 @@ spec:
fieldPath: metadata.name
args:
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
+ - -report-ingress-status
+ - -external-service=nginx-ingress
#- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
#- -include-year
#- -enable-cert-manager
#- -enable-external-dns
#- -v=3 # Enables extensive logging. Useful for troubleshooting.
- #- -report-ingress-status
- #- -external-service=nginx-ingress
#- -enable-prometheus-metrics
#- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
# initContainers:
diff --git a/deployments/deployment/nginx-plus-ingress.yaml b/deployments/deployment/nginx-plus-ingress.yaml
index baabdcefe0..74f7e3b560 100644
--- a/deployments/deployment/nginx-plus-ingress.yaml
+++ b/deployments/deployment/nginx-plus-ingress.yaml
@@ -90,6 +90,8 @@ spec:
args:
- -nginx-plus
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
+ - -report-ingress-status
+ - -external-service=nginx-ingress
#- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
#- -include-year
#- -enable-cert-manager
@@ -97,8 +99,6 @@ spec:
#- -enable-app-protect
#- -enable-app-protect-dos
#- -v=3 # Enables extensive logging. Useful for troubleshooting.
- #- -report-ingress-status
- #- -external-service=nginx-ingress
#- -enable-prometheus-metrics
#- -enable-service-insight
#- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
From f6717e173d526a0994618a4eebc5ef0a5e4ad5b5 Mon Sep 17 00:00:00 2001
From: Shaun
Date: Wed, 12 Jun 2024 17:22:46 +0100
Subject: [PATCH 10/38] Integrate NAP WAF v5 (#5698)
---
.github/config/config-plus-gcr-release | 1 +
.github/config/config-plus-nginx | 1 +
.github/scripts/copy-images.sh | 29 +++
.github/workflows/build-plus.yml | 3 +-
.github/workflows/ci.yml | 16 ++
Makefile | 35 ++-
build/Dockerfile | 187 ++++++++++++++--
build/scripts/agent.sh | 14 +-
build/scripts/nap-waf.sh | 11 +-
charts/nginx-ingress/README.md | 14 ++
charts/nginx-ingress/templates/_helpers.tpl | 71 +++++-
.../templates/controller-daemonset.yaml | 3 +
.../templates/controller-deployment.yaml | 3 +
charts/nginx-ingress/values.schema.json | 204 ++++++++++++++++++
charts/nginx-ingress/values.yaml | 59 ++++-
cmd/nginx-ingress/flags.go | 11 +-
cmd/nginx-ingress/main.go | 31 ++-
internal/configs/config_params.go | 3 +
internal/configs/configmaps.go | 2 +
internal/configs/configurator.go | 1 -
internal/configs/version1/config.go | 2 +
internal/configs/version1/nginx-plus.tmpl | 4 +
internal/configs/version2/templates_test.go | 2 +-
internal/configs/virtualserver.go | 3 +-
internal/configs/virtualserver_test.go | 8 +-
25 files changed, 664 insertions(+), 54 deletions(-)
diff --git a/.github/config/config-plus-gcr-release b/.github/config/config-plus-gcr-release
index 0af0ae550d..0a29939d56 100644
--- a/.github/config/config-plus-gcr-release
+++ b/.github/config/config-plus-gcr-release
@@ -1,6 +1,7 @@
export TARGET_REGISTRY=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/release
declare -a PLUS_TAG_POSTFIX_LIST=("" "-ubi" "-alpine" "-alpine-fips" "-mktpl" "-alpine-mktpl" "-alpine-mktpl-fips")
declare -a NAP_WAF_TAG_POSTFIX_LIST=("" "-ubi" "-mktpl" "-ubi-mktpl" "-alpine-fips")
+declare -a NAP_WAFV5_TAG_POSTFIX_LIST=("" "-ubi" "-alpine-fips")
declare -a NAP_DOS_TAG_POSTFIX_LIST=("" "-ubi" "-mktpl" "-ubi-mktpl")
declare -a NAP_WAF_DOS_TAG_POSTFIX_LIST=("" "-ubi" "-mktpl" "-ubi-mktpl")
declare -a ADDITIONAL_TAGS=("latest" "${ADDITIONAL_TAG}")
diff --git a/.github/config/config-plus-nginx b/.github/config/config-plus-nginx
index de809c41b8..969f28b4d1 100644
--- a/.github/config/config-plus-nginx
+++ b/.github/config/config-plus-nginx
@@ -2,6 +2,7 @@ export TARGET_REGISTRY=docker-mgmt.nginx.com
export TARGET_NAP_WAF_DOS_IMAGE_PREFIX="nginx-ic-nap-dos/nginx-plus-ingress"
declare -a PLUS_TAG_POSTFIX_LIST=("" "-ubi" "-alpine" "-alpine-fips")
declare -a NAP_WAF_TAG_POSTFIX_LIST=("" "-ubi" "-alpine-fips")
+declare -a NAP_WAFV5_TAG_POSTFIX_LIST=("" "-ubi" "-alpine-fips")
declare -a NAP_DOS_TAG_POSTFIX_LIST=("" "-ubi")
declare -a NAP_WAF_DOS_TAG_POSTFIX_LIST=("" "-ubi")
declare -a ADDITIONAL_TAGS=("latest" "${ADDITIONAL_TAG}")
diff --git a/.github/scripts/copy-images.sh b/.github/scripts/copy-images.sh
index b63fa618e5..b729509a8e 100755
--- a/.github/scripts/copy-images.sh
+++ b/.github/scripts/copy-images.sh
@@ -28,19 +28,25 @@ TARGET_OSS_IMAGE_PREFIX=${TARGET_OSS_IMAGE_PREFIX:-"nginx-ic/nginx-ingress"}
SOURCE_PLUS_IMAGE_PREFIX=${SOURCE_PLUS_IMAGE_PREFIX:-"nginx-ic/nginx-plus-ingress"}
SOURCE_NAP_WAF_IMAGE_PREFIX=${SOURCE_NAP_WAF_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
+SOURCE_NAP_WAFV5_IMAGE_PREFIX=${SOURCE_NAP_WAFV5_IMAGE_PREFIX:-"nginx-ic-nap-v5/nginx-plus-ingress"}
SOURCE_NAP_DOS_IMAGE_PREFIX=${SOURCE_NAP_DOS_IMAGE_PREFIX:-"nginx-ic-dos/nginx-plus-ingress"}
SOURCE_NAP_WAF_DOS_IMAGE_PREFIX=${SOURCE_NAP_WAF_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap/nginx-plus-ingress"}
+SOURCE_NAP_WAFV5_DOS_IMAGE_PREFIX=${SOURCE_NAP_WAFV5_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap-v5/nginx-plus-ingress"}
TARGET_PLUS_IMAGE_PREFIX=${TARGET_PLUS_IMAGE_PREFIX:-"nginx-ic/nginx-plus-ingress"}
TARGET_NAP_WAF_IMAGE_PREFIX=${TARGET_NAP_WAF_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
+TARGET_NAP_WAFV5_IMAGE_PREFIX=${TARGET_NAP_WAFV5_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
TARGET_NAP_DOS_IMAGE_PREFIX=${TARGET_NAP_DOS_IMAGE_PREFIX:-"nginx-ic-dos/nginx-plus-ingress"}
TARGET_NAP_WAF_DOS_IMAGE_PREFIX=${TARGET_NAP_WAF_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap/nginx-plus-ingress"}
+TARGET_NAP_WAFV5_DOS_IMAGE_PREFIX=${TARGET_NAP_WAFV5_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap-v5/nginx-plus-ingress"}
declare -a OSS_TAG_POSTFIX_LIST=("" "-ubi" "-alpine")
declare -a PLUS_TAG_POSTFIX_LIST=("" "-ubi" "-alpine" "-alpine-fips")
declare -a NAP_WAF_TAG_POSTFIX_LIST=("" "-ubi" "-alpine-fips")
+declare -a NAP_WAFV5_TAG_POSTFIX_LIST=()
declare -a NAP_DOS_TAG_POSTFIX_LIST=("" "-ubi")
declare -a NAP_WAF_DOS_TAG_POSTFIX_LIST=("" "-ubi")
+declare -a NAP_WAFV5_DOS_TAG_POSTFIX_LIST=()
declare -a ADDITIONAL_TAGS=("latest" "${ADDITIONAL_TAG}")
CONFIG_PATH=${CONFIG_PATH:-~/.nic-release/config}
@@ -152,6 +158,29 @@ if $PUBLISH_WAF; then
done
fi
done
+ for postfix in "${NAP_WAFV5_TAG_POSTFIX_LIST[@]}"; do
+ image=${SOURCE_REGISTRY}/${SOURCE_NAP_WAFV5_IMAGE_PREFIX}:${SOURCE_TAG}${postfix}
+ echo "Processing image ${image}"
+ new_tag=${TARGET_REGISTRY}/${TARGET_NAP_WAFV5_IMAGE_PREFIX}:${TARGET_TAG}${postfix}
+ if $IS_IMMUTABLE && skopeo --override-os linux --override-arch amd64 inspect docker://${new_tag} > /dev/null 2>&1; then
+ echo " ECR is immutable & tag ${new_tag} already exists, skipping."
+ else
+ echo " Pushing image NAP WAFV5 ${new_tag}..."
+ if ! $DRY_RUN; then
+ skopeo copy --retry-times 5 ${ARCH_OPTS} ${SOURCE_OPTS} ${TARGET_OPTS} docker://${image} docker://${new_tag}
+ fi
+ for tag in "${ADDITIONAL_TAGS[@]}"; do
+ if [ -z "${tag}" ]; then
+ continue
+ fi
+ additional_tag=${TARGET_REGISTRY}/${TARGET_NAP_WAFV5_IMAGE_PREFIX}:${tag}${postfix}
+ echo " Pushing image NAP WAFV5 ${additional_tag}..."
+ if ! $DRY_RUN; then
+ skopeo copy --retry-times 5 ${ARCH_OPTS} ${SOURCE_OPTS} ${TARGET_OPTS} docker://${image} docker://${additional_tag}
+ fi
+ done
+ fi
+ done
else
echo "Skipping Publish Plus WAF flow"
fi
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 8a0f507e20..e689efc1d2 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -107,7 +107,7 @@ jobs:
cache-from: type=gha,scope=${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
cache-to: type=gha,scope=${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
target: common
- tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
+ tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}
platforms: ${{ inputs.platforms }}
pull: true
push: true
@@ -187,6 +187,7 @@ jobs:
IC_VERSION=${{ steps.meta.outputs.version }}
${{ inputs.nap_modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
${{ (contains(inputs.target, 'aws') && inputs.nap_modules != '') && format('NAP_MODULES_AWS={0}', steps.nap_modules.outputs.modules) || '' }}
+ ${{ contains(inputs.image, 'v5') && 'WAF_VERSION=v5' || '' }}
secrets: |
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
"nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b4c1b19ab8..16aec5331a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -369,6 +369,22 @@ jobs:
target: goreleaser
platforms: "linux/amd64"
nap_modules: waf
+ - image: alpine-plus-nap-v5-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: debian-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-9-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
uses: ./.github/workflows/build-plus.yml
with:
platforms: ${{ matrix.platforms }}
diff --git a/Makefile b/Makefile
index 94468a59ab..486634438d 100644
--- a/Makefile
+++ b/Makefile
@@ -31,8 +31,8 @@ export DOCKER_BUILDKIT = 1
.PHONY: help
help: Makefile ## Display this help
- @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "; printf "Usage:\n\n make \033[36m\033[0m [VARIABLE=value...]\n\nTargets:\n\n"}; {printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}'
- @grep -E '^(override )?[a-zA-Z_-]+ \??\+?= .*? ## .*$$' $< | sort | awk 'BEGIN {FS = " \\??\\+?= .*? ## "; printf "\nVariables:\n\n"}; {gsub(/override /, "", $$1); printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}'
+ @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "; printf "Usage:\n\n make \033[36m\033[0m [VARIABLE=value...]\n\nTargets:\n\n"}; {printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}'
+ @grep -E '^(override )?[a-zA-Z0-9_-]+ \??\+?= .*? ## .*$$' $< | sort | awk 'BEGIN {FS = " \\??\\+?= .*? ## "; printf "\nVariables:\n\n"}; {gsub(/override /, "", $$1); printf " \033[36m%-30s\033[0m %s\n", $$1, $$2}'
.PHONY: all
all: test lint verify-codegen update-crds debian-image
@@ -141,6 +141,13 @@ alpine-image-plus-fips: build ## Create Docker image for Ingress Controller (Alp
alpine-image-nap-plus-fips: build ## Create Docker image for Ingress Controller (Alpine with NGINX Plus, NGINX App Protect WAF and FIPS)
$(DOCKER_CMD) $(PLUS_ARGS) --build-arg BUILD_OS=alpine-plus-nap-fips --build-arg NGINX_AGENT=$(NGINX_AGENT)
+.PHONY: alpine-image-nap-v5-plus-fips
+alpine-image-nap-v5-plus-fips: build ## Create Docker image for Ingress Controller (Alpine with NGINX Plus, NGINX App Protect WAFv5 and FIPS)
+ $(DOCKER_CMD) $(PLUS_ARGS) \
+ --build-arg BUILD_OS=alpine-plus-nap-v5-fips \
+ --build-arg NGINX_AGENT=$(NGINX_AGENT) \
+ --build-arg WAF_VERSION=v5
+
.PHONY: debian-image-plus
debian-image-plus: build ## Create Docker image for Ingress Controller (Debian with NGINX Plus)
$(DOCKER_CMD) $(PLUS_ARGS) --build-arg BUILD_OS=debian-plus
@@ -149,6 +156,14 @@ debian-image-plus: build ## Create Docker image for Ingress Controller (Debian w
debian-image-nap-plus: build ## Create Docker image for Ingress Controller (Debian with NGINX Plus and NGINX App Protect WAF)
$(DOCKER_CMD) $(PLUS_ARGS) --build-arg BUILD_OS=debian-plus-nap --build-arg NAP_MODULES=waf --build-arg NGINX_AGENT=$(NGINX_AGENT)
+.PHONY: debian-image-nap-v5-plus
+debian-image-nap-v5-plus: build ## Create Docker image for Ingress Controller (Debian with NGINX Plus and NGINX App Protect WAFv5)
+ $(DOCKER_CMD) $(PLUS_ARGS) \
+ --build-arg BUILD_OS=debian-plus-nap-v5 \
+ --build-arg NAP_MODULES=waf \
+ --build-arg NGINX_AGENT=$(NGINX_AGENT) \
+ --build-arg WAF_VERSION=v5
+
.PHONY: debian-image-dos-plus
debian-image-dos-plus: build ## Create Docker image for Ingress Controller (Debian with NGINX Plus and NGINX App Protect DoS)
$(DOCKER_CMD) $(PLUS_ARGS) --build-arg BUILD_OS=debian-plus-nap --build-arg NAP_MODULES=dos
@@ -169,6 +184,14 @@ ubi-image-plus: build ## Create Docker image for Ingress Controller (UBI with NG
ubi-image-nap-plus: build ## Create Docker image for Ingress Controller (UBI with NGINX Plus and NGINX App Protect WAF)
$(DOCKER_CMD) $(PLUS_ARGS) --secret id=rhel_license,src=rhel_license --build-arg BUILD_OS=ubi-9-plus-nap --build-arg NAP_MODULES=waf --build-arg NGINX_AGENT=$(NGINX_AGENT)
+.PHONY: ubi-image-nap-v5-plus
+ubi-image-nap-v5-plus: build ## Create Docker image for Ingress Controller (UBI with NGINX Plus and NGINX App Protect WAFv5)
+ $(DOCKER_CMD) $(PLUS_ARGS) --secret id=rhel_license,src=rhel_license \
+ --build-arg BUILD_OS=ubi-9-plus-nap-v5 \
+ --build-arg NAP_MODULES=waf \
+ --build-arg NGINX_AGENT=$(NGINX_AGENT) \
+ --build-arg WAF_VERSION=v5
+
.PHONY: ubi-image-dos-plus
ubi-image-dos-plus: build ## Create Docker image for Ingress Controller (UBI with NGINX Plus and NGINX App Protect DoS)
$(DOCKER_CMD) $(PLUS_ARGS) --secret id=rhel_license,src=rhel_license --build-arg BUILD_OS=ubi-8-plus-nap --build-arg NAP_MODULES=dos
@@ -177,6 +200,14 @@ ubi-image-dos-plus: build ## Create Docker image for Ingress Controller (UBI wit
ubi-image-nap-dos-plus: build ## Create Docker image for Ingress Controller (UBI with NGINX Plus, NGINX App Protect WAF and DoS)
$(DOCKER_CMD) $(PLUS_ARGS) --secret id=rhel_license,src=rhel_license --build-arg BUILD_OS=ubi-8-plus-nap --build-arg NAP_MODULES=waf,dos --build-arg NGINX_AGENT=$(NGINX_AGENT)
+.PHONY: ubi-image-nap-dos-v5-plus
+ubi-image-nap-dos-v5-plus: build ## Create Docker image for Ingress Controller (UBI with NGINX Plus, NGINX App Protect WAFv5 and DoS)
+ $(DOCKER_CMD) $(PLUS_ARGS) --secret id=rhel_license,src=rhel_license \
+ --build-arg BUILD_OS=ubi-8-plus-nap-v5 \
+ --build-arg NAP_MODULES=waf,dos \
+ --build-arg NGINX_AGENT=$(NGINX_AGENT) \
+ --build-arg WAF_VERSION=v5
+
.PHONY: all-images ## Create all the Docker images for Ingress Controller
all-images: alpine-image alpine-image-plus alpine-image-plus-fips alpine-image-nap-plus-fips debian-image debian-image-plus debian-image-nap-plus debian-image-dos-plus debian-image-nap-dos-plus ubi-image ubi-image-plus ubi-image-nap-plus ubi-image-dos-plus ubi-image-nap-dos-plus
diff --git a/build/Dockerfile b/build/Dockerfile
index 7fbbdd2590..935e53dde8 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -6,6 +6,7 @@ ARG DEBIAN_FRONTEND=noninteractive
ARG PREBUILT_BASE_IMG=nginx/nginx-ingress:${DOWNLOAD_TAG}
ARG NGINX_AGENT=false
ARG IMAGE_NAME=nginx/nginx-ingress
+ARG WAF_VERSION=v4
############################################# Base images containing libs for Opentracing and FIPS #############################################
@@ -13,7 +14,7 @@ FROM ghcr.io/nginxinc/k8s-common:nginx-opentracing-1.27.0@sha256:d9f6f930b7bfcc0
FROM ghcr.io/nginxinc/k8s-common:nginx-opentracing-1.27.0-alpine@sha256:5dc5c76384a775316c541995b145d4cef86d529934951319fd127f4d4fdb9ef7 as alpine-opentracing-lib
FROM ghcr.io/nginxinc/alpine-fips:0.1.0-alpine3.17@sha256:f00b3f266422feaaac7b733b46903bd19eb1cd1caa6991131576f5f767db76f8 as alpine-fips-3.17
FROM ghcr.io/nginxinc/alpine-fips:0.2.0-alpine3.19@sha256:1744ae3a8e795daf771f3f7df33b83160981545abb1f1597338e2769d06aa1cc as alpine-fips-3.19
-FROM redhat/ubi9-minimal@sha256:0d6b09f233745d2fcf892cebcf1c18bbfed497f116bc8357e9db4b724d76c5a9 AS ubi-minimal
+FROM redhat/ubi9-minimal@sha256:2636170dc55a0931d013014a72ae26c0c2521d4b61a28354b3e2e5369fa335a3 AS ubi-minimal
FROM golang:1.22-alpine@sha256:9bdd5692d39acc3f8d0ea6f81327f87ac6b473dd29a2b6006df362bff48dd1f8 as golang-builder
@@ -71,17 +72,21 @@ ADD --link --chown=101:0 https://cs.nginx.com/static/files/nginx-plus-8.repo ngi
ADD --link --chown=101:0 https://cs.nginx.com/static/files/plus-9.repo nginx-plus-9.repo
ADD --link --chown=101:0 https://cs.nginx.com/static/files/app-protect-8.repo app-protect-8.repo
ADD --link --chown=101:0 https://cs.nginx.com/static/files/app-protect-9.repo app-protect-9.repo
+ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-waf-v5-ubi-8.repo app-protect-v5-8.repo
+ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-waf-v5-ubi-9.repo app-protect-v5-9.repo
ADD --link --chown=101:0 https://cs.nginx.com/static/files/app-protect-dos-8.repo app-protect-dos-8.repo
ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/plus-debian-11.repo debian-plus-11.sources
ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/plus-debian-12.repo debian-plus-12.sources
ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-waf-debian-11.repo nap-waf-11.sources
ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-dos-debian-11.repo nap-dos-11.sources
+ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-waf-v5-debian-12.repo nap-waf-v5-12.sources
ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/agent-debian-11.repo debian-agent-11.sources
RUN --mount=from=busybox:musl,src=/bin/,dst=/bin/ printf "%s\n" "Acquire::https::pkgs.nginx.com::User-Agent k8s-ic-$IC_VERSION${BUILD_OS##debian-plus}-apt;" >> 90pkgs-nginx \
&& printf "%s\n" "user_agent=k8s-ic-$IC_VERSION${BUILD_OS##ubi*plus}-dnf" | tee -a nginx-plus-*.repo \
&& sed -i -e "s;%VERSION%;${NGINX_PLUS_VERSION};g" *.sources \
- && sed -i -e "y/0/1/" -e "1,8s;/centos;/${NGINX_PLUS_VERSION}/centos;" *.repo \
+ && sed -i -e "y/0/1/" app-protect-v5-*.repo \
+ && sed -i -e "y/0/1/" -e "1,8s;/centos;/${NGINX_PLUS_VERSION}/centos;" nginx-plus-*.repo app-protect-?.repo app-protect-dos-8.repo \
&& echo HTTP_USER_AGENT="k8s-ic-$IC_VERSION${BUILD_OS##alpine-plus}-apk" > user_agent
ADD --link --chown=101:0 https://cs.nginx.com/static/files/nginx-agent.repo nginx-agent.repo
@@ -106,6 +111,7 @@ RUN --mount=type=bind,from=nginx-files,src=patch-os.sh,target=/usr/local/bin/pat
&& patch-os.sh
USER 101
+
############################################# Base image for Alpine with NGINX Plus #############################################
FROM alpine:3.19@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b as alpine-plus
ARG NGINX_PLUS_VERSION
@@ -136,6 +142,7 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \
############################################# Base image for Alpine with NGINX Plus, App Protect WAF and FIPS #############################################
FROM alpine:3.17@sha256:53cf9478b76f4c8fae126acbdfb79bed6e69e628faff572ebe4a029d3d247d98 as alpine-plus-nap-fips
ARG NGINX_PLUS_VERSION
+ARG NGINX_AGENT
RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
--mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
@@ -150,7 +157,7 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
&& printf "%s\n" "https://pkgs.nginx.com/app-protect-security-updates/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
&& printf "%s\n" "https://pkgs.nginx.com/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
&& apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-opentracing nginx-plus-module-fips-check \
- && if [ -z "${NGINX_AGENT##true}" ]; then apk add --no-cache nginx-agent; fi \
+ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \
&& mkdir -p /usr/ssl \
&& cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \
&& cp -av /tmp/fips/usr/ssl/fipsmodule.cnf /usr/ssl/fipsmodule.cnf \
@@ -160,11 +167,41 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
&& apk add --no-cache app-protect app-protect-attack-signatures app-protect-threat-campaigns \
&& sed -i -e '/nginx.com/d' /etc/apk/repositories \
&& nap-waf.sh \
- && if [ -z "${NGINX_AGENT##true}" ]; then \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
agent.sh \
; fi
+############################################# Base image for Alpine with NGINX Plus, App Protect WAFv5 and FIPS #############################################
+FROM alpine:3.17@sha256:53cf9478b76f4c8fae126acbdfb79bed6e69e628faff572ebe4a029d3d247d98 as alpine-plus-nap-v5-fips
+ARG NGINX_PLUS_VERSION
+ARG NGINX_AGENT
+
+RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
+ --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
+ --mount=type=secret,id=nginx-repo.key,dst=/etc/apk/cert.key,mode=0644 \
+ --mount=type=bind,from=alpine-opentracing-lib,target=/tmp/ot/ \
+ --mount=type=bind,from=nginx-files,src=nginx_signing.rsa.pub,target=/etc/apk/keys/nginx_signing.rsa.pub \
+ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \
+ --mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \
+ printf "%s\n" "https://pkgs.nginx.com/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
+ && printf "%s\n" "https://pkgs.nginx.com/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
+ && printf "%s\n" "https://pkgs.nginx.com/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \
+ && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-opentracing nginx-plus-module-fips-check \
+ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \
+ && mkdir -p /usr/ssl \
+ && cp -av /tmp/fips/usr/lib/ossl-modules/fips.so /usr/lib/ossl-modules/fips.so \
+ && cp -av /tmp/fips/usr/ssl/fipsmodule.cnf /usr/ssl/fipsmodule.cnf \
+ && cp -av /tmp/fips/etc/ssl/openssl.cnf /etc/ssl/openssl.cnf \
+ && cp -av /tmp/ot/usr/local/lib/libjaegertracing*so* /tmp/ot/usr/local/lib/libzipkin*so* /tmp/ot/usr/local/lib/libdd*so* /tmp/ot/usr/local/lib/libyaml*so* /usr/local/lib/ \
+ && ldconfig /usr/local/lib/ \
+ && apk add --no-cache app-protect-module-plus \
+ && sed -i -e '/nginx.com/d' /etc/apk/repositories \
+ && nap-waf.sh \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
+ agent.sh \
+ ; fi
+
############################################# Base image for Debian with NGINX Plus #############################################
FROM debian:12-slim@sha256:804194b909ef23fb995d9412c9378fb3505fe2427b70f3cc425339e48a828fca AS debian-plus
@@ -192,6 +229,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
############################################# Base image for Debian with NGINX Plus and App Protect WAF/DoS #############################################
FROM debian:11-slim@sha256:0e75382930ceb533e2f438071307708e79dc86d9b8e433cc6dd1a96872f2651d as debian-plus-nap
ARG NAP_MODULES
+ARG NGINX_AGENT
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -222,7 +260,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& apt-get update \
&& apt-get install --no-install-recommends --no-install-suggests -y nginx-plus nginx-plus-module-njs nginx-plus-module-opentracing nginx-plus-module-fips-check libcap2-bin libcurl4 \
## end of duplicated code
- && if [ -z "${NGINX_AGENT##true}" ]; then apt-get install --no-install-recommends --no-install-suggests -y nginx-agent; fi \
+ && if [ "${NGINX_AGENT}" = "true" ]; then apt-get install --no-install-recommends --no-install-suggests -y nginx-agent; fi \
&& if [ -z "${NAP_MODULES##*waf*}" ]; then \
apt-get install --no-install-recommends --no-install-suggests -y app-protect app-protect-attack-signatures app-protect-threat-campaigns; \
fi \
@@ -243,7 +281,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& rm -rf /var/lib/apt/lists/* \
&& if [ -z "${NAP_MODULES##*waf*}" ]; then \
nap-waf.sh \
- && if [ -z "${NGINX_AGENT##true}" ]; then \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
agent.sh \
; fi \
; fi \
@@ -251,9 +289,32 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
nap-dos.sh \
; fi
-# Uncomment the lines below if you want to install a custom CA certificate
-# COPY build/*.crt /usr/local/share/ca-certificates/
-# RUN update-ca-certificates
+############################################# Base image for Debian with NGINX Plus and App Protect WAFv5/DoS #############################################
+FROM debian-plus as debian-plus-nap-v5
+ARG NAP_MODULES
+ARG NGINX_AGENT
+
+RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
+ --mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
+ --mount=type=bind,from=nginx-files,src=90pkgs-nginx,target=/etc/apt/apt.conf.d/90pkgs-nginx \
+ --mount=type=bind,from=nginx-files,src=nap-waf-v5-12.sources,target=/tmp/app-protect.sources \
+ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \
+ --mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \
+ --mount=type=bind,from=nginx-files,src=debian-agent-11.sources,target=/etc/apt/sources.list.d/nginx-agent.sources \
+ if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ cp /tmp/app-protect.sources /etc/apt/sources.list.d/app-protect.sources; \
+ fi \
+ && apt-get update \
+ && if [ "${NGINX_AGENT}" = "true" ]; then apt-get install --no-install-recommends --no-install-suggests -y nginx-agent; fi \
+ && if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ apt-get install --no-install-recommends --no-install-suggests -y app-protect-module-plus; \
+ rm -f /etc/apt/sources.list.d/app-protect.sources; \
+ nap-waf.sh; \
+ fi \
+ && apt-get purge --auto-remove -y gpg \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
+ agent.sh; \
+ fi
############################################# Base image for UBI with NGINX Plus #############################################
@@ -277,6 +338,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
############################################# Base image for UBI with NGINX Plus and App Protect WAF #############################################
FROM ubi-minimal as ubi-9-plus-nap
ARG NAP_MODULES
+ARG NGINX_AGENT
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -295,7 +357,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \
&& rpm --import /tmp/nginx_signing.key \
&& microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \
- && if [ -z "${NGINX_AGENT##true}" ]; then microdnf --nodocs install -y nginx-agent; fi \
+ && if [ "${NGINX_AGENT}" = "true" ]; then microdnf --nodocs install -y nginx-agent; fi \
&& subscription-manager register --org=${RHEL_ORGANIZATION} --activationkey=${RHEL_ACTIVATION_KEY} || true \
&& subscription-manager attach \
&& rpm --import /tmp/app-protect-security-updates.key \
@@ -309,13 +371,57 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& subscription-manager unregister \
&& microdnf remove -y shadow-utils subscription-manager \
&& microdnf clean all && rm -rf /var/cache/dnf \
- && if [ -z "${NGINX_AGENT##true}" ]; then \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
agent.sh \
; fi
+
+############################################# Base image for UBI with NGINX Plus and App Protect WAFv5 #############################################
+FROM ubi-minimal as ubi-9-plus-nap-v5
+ARG NAP_MODULES
+ARG NGINX_AGENT
+
+RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
+ --mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
+ --mount=type=secret,id=rhel_license,dst=/tmp/rhel_license,mode=0644 \
+ --mount=type=bind,from=nginx-files,src=nginx_signing.key,target=/tmp/nginx_signing.key \
+ --mount=type=bind,from=nginx-files,src=nginx-plus-9.repo,target=/etc/yum.repos.d/nginx-plus.repo,rw \
+ --mount=type=bind,from=nginx-files,src=nginx-agent.repo,target=/etc/yum.repos.d/nginx-agent.repo,rw \
+ --mount=type=bind,from=nginx-files,src=app-protect-v5-9.repo,target=/tmp/app-protect-9.repo \
+ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \
+ --mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \
+ source /tmp/rhel_license \
+ && rpm -ivh https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm \
+ && microdnf --nodocs install -y shadow-utils ca-certificates subscription-manager \
+ && groupadd --system --gid 101 nginx \
+ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \
+ && rpm --import /tmp/nginx_signing.key \
+ && microdnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \
+ && if [ "${NGINX_AGENT}" = "true" ]; then microdnf --nodocs install -y nginx-agent; fi \
+ && subscription-manager register --org=${RHEL_ORGANIZATION} --activationkey=${RHEL_ACTIVATION_KEY} || true \
+ && subscription-manager attach \
+ && if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ cp /tmp/app-protect-9.repo /etc/yum.repos.d/app-protect-9.repo; \
+ fi \
+ && if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ cp /tmp/app-protect-9.repo /etc/yum.repos.d/app-protect-9.repo \
+ && microdnf --enablerepo=codeready-builder-for-rhel-9-x86_64-rpms --nodocs install -y app-protect-module-plus \
+ && rm -f /etc/yum.repos.d/app-protect-9.repo \
+ && nap-waf.sh \
+ && rm -f /etc/yum.repos.d/app-protect-9.repo; \
+ fi \
+ && subscription-manager unregister \
+ && microdnf remove -y shadow-utils subscription-manager \
+ && microdnf clean all && rm -rf /var/cache/dnf \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
+ agent.sh; \
+ fi
+
+
############################################# Base image for UBI with NGINX Plus and App Protect WAF & DoS #############################################
FROM redhat/ubi8@sha256:143123d85045df426c5bbafc6863659880ebe276eb02c77ee868b88d08dbd05d as ubi-8-plus-nap
ARG NAP_MODULES
+ARG NGINX_AGENT
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -328,6 +434,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
--mount=type=bind,from=nginx-files,src=app-protect-dos-8.repo,target=/tmp/app-protect-dos-8.repo \
--mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \
--mount=type=bind,from=nginx-files,src=nap-dos.sh,target=/usr/local/bin/nap-dos.sh \
+ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \
source /tmp/rhel_license \
&& if [ -z "${NAP_MODULES##*waf*}" ]; then \
cp /tmp/app-protect-8.repo /etc/yum.repos.d/app-protect-8.repo; \
@@ -340,7 +447,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \
&& rpm --import /tmp/nginx_signing.key \
&& dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \
- && if [ -z "${NGINX_AGENT##true}" ]; then dnf --nodocs install -y nginx-agent; fi \
+ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \
## end of duplicated code
## fix for CVEs
&& sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \
@@ -366,11 +473,55 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
rm -f /etc/yum.repos.d/app-protect-dos-8.repo \
&& nap-dos.sh; \
fi \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
+ agent.sh; \
+ fi \
&& dnf clean all
-# Uncomment the lines below if you want to install a custom CA certificate
-# COPY build/*.crt /etc/pki/ca-trust/source/anchors/
-# RUN update-ca-trust extract
+
+############################################# Base image for UBI with NGINX Plus and App Protect WAFv5 #############################################
+FROM redhat/ubi8@sha256:f4292f415f60632a0ff9c0646c4fa859d8b2e1e88a16faa90c6decd1951aea88 as ubi-8-plus-nap-v5
+ARG NAP_MODULES
+ARG NGINX_AGENT
+
+RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
+ --mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
+ --mount=type=secret,id=rhel_license,dst=/tmp/rhel_license,mode=0644 \
+ --mount=type=bind,from=nginx-files,src=nginx_signing.key,target=/tmp/nginx_signing.key \
+ --mount=type=bind,from=nginx-files,src=nginx-plus-8.repo,target=/etc/yum.repos.d/nginx-plus.repo,rw \
+ --mount=type=bind,from=nginx-files,src=nginx-agent.repo,target=/etc/yum.repos.d/nginx-agent.repo,rw \
+ --mount=type=bind,from=nginx-files,src=app-protect-v5-8.repo,target=/tmp/app-protect-8.repo \
+ --mount=type=bind,from=nginx-files,src=app-protect-dos-8.repo,target=/tmp/app-protect-dos-8.repo \
+ --mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \
+ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \
+ source /tmp/rhel_license \
+ && if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ cp /tmp/app-protect-8.repo /etc/yum.repos.d/app-protect-8.repo; \
+ fi \
+ ## the code below is duplicated from the ubi-plus image because NAP DOS doesn't support UBI 9 and minimal versions
+ && groupadd --system --gid 101 nginx \
+ && useradd --system --gid nginx --no-create-home --home-dir /nonexistent --comment "nginx user" --shell /bin/false --uid 101 nginx \
+ && rpm --import /tmp/nginx_signing.key \
+ && dnf --nodocs install -y nginx-plus nginx-plus-module-njs nginx-plus-module-fips-check \
+ && if [ "${NGINX_AGENT}" = "true" ]; then dnf --nodocs install -y nginx-agent; fi \
+ ## end of duplicated code
+ && sed -i 's/\(def in_container():\)/\1\n return False/g' /usr/lib64/python*/*-packages/rhsm/config.py \
+ && subscription-manager register --org=${RHEL_ORGANIZATION} --activationkey=${RHEL_ACTIVATION_KEY} || true \
+ && subscription-manager attach \
+ && dnf config-manager --set-enabled codeready-builder-for-rhel-8-x86_64-rpms \
+ && dnf --nodocs install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm \
+ && if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ dnf --nodocs install -y app-protect-module-plus; \
+ fi \
+ && subscription-manager unregister \
+ && if [ -z "${NAP_MODULES##*waf*}" ]; then \
+ rm -f /etc/yum.repos.d/app-protect-8.repo \
+ && nap-waf.sh; \
+ fi \
+ && if [ "${NGINX_AGENT}" = "true" ]; then \
+ agent.sh; \
+ fi \
+ && dnf clean all
############################################# Create common files, permissions and setcap #############################################
@@ -387,10 +538,6 @@ RUN --mount=type=bind,target=/tmp \
patch-os.sh \
&& common.sh
-# Uncomment the line below if you would like to add the default.pem to the image
-# and use it as a certificate and key for the default server
-# ADD default.pem /etc/nginx/secrets/default
-
EXPOSE 80 443
STOPSIGNAL SIGTERM
@@ -420,6 +567,7 @@ RUN --mount=type=bind,target=/go/src/github.com/nginxinc/kubernetes-ingress/ --m
-o /nginx-ingress github.com/nginxinc/kubernetes-ingress/cmd/nginx-ingress \
&& setcap 'cap_net_bind_service=+ep' /nginx-ingress && setcap -v 'cap_net_bind_service=+ep' /nginx-ingress
+
############################################# Download delve #############################################
FROM golang-builder AS debug-builder
ARG TARGETARCH
@@ -560,6 +708,7 @@ COPY --link --chown=101:0 dist/aws*${NAP_MODULES_AWS}_linux_${TARGETARCH}*/nginx
USER 0
RUN setcap 'cap_net_bind_service=+ep' /nginx-ingress && setcap -v 'cap_net_bind_service=+ep' /nginx-ingress
+
############################################# Create image with nginx-ingress built by GoReleaser for AWS Marketplace #############################################
FROM common AS aws
ARG TARGETARCH
diff --git a/build/scripts/agent.sh b/build/scripts/agent.sh
index b304b0c7c7..0cb6a07ffd 100755
--- a/build/scripts/agent.sh
+++ b/build/scripts/agent.sh
@@ -2,9 +2,13 @@
set -e
-NAP_VERSION=$(cat /opt/app_protect/VERSION)
-mkdir -p /etc/ssl/nms /opt/nms-nap-compiler
-chown -R 101:0 /etc/ssl/nms /opt/nms-nap-compiler
-chmod -R g=u /etc/ssl/nms /opt/nms-nap-compiler
-ln -s /opt/app_protect "/opt/nms-nap-compiler/app_protect-${NAP_VERSION}"
+if [ -z "${WAF_VERSION##*v4*}" ]; then
+ NAP_VERSION=$(cat /opt/app_protect/VERSION)
+
+ mkdir -p /etc/ssl/nms /opt/nms-nap-compiler
+ chown -R 101:0 /etc/ssl/nms /opt/nms-nap-compiler
+ chmod -R g=u /etc/ssl/nms /opt/nms-nap-compiler
+
+ ln -s /opt/app_protect "/opt/nms-nap-compiler/app_protect-${NAP_VERSION}"
+fi
diff --git a/build/scripts/nap-waf.sh b/build/scripts/nap-waf.sh
index 5d295ea500..cf736732d7 100755
--- a/build/scripts/nap-waf.sh
+++ b/build/scripts/nap-waf.sh
@@ -2,7 +2,12 @@
set -e
-mkdir -p /etc/nginx/waf/nac-policies /etc/nginx/waf/nac-logconfs /etc/nginx/waf/nac-usersigs /var/log/app_protect /opt/app_protect
-chown -R 101:0 /etc/app_protect /usr/share/ts /var/log/app_protect/ /opt/app_protect/
-chmod -R g=u /etc/app_protect /usr/share/ts /var/log/app_protect/ /opt/app_protect/
+for i in /etc/nginx/waf/nac-policies /etc/nginx/waf/nac-logconfs /etc/nginx/waf/nac-usersigs /etc/app_protect /usr/share/ts /var/log/app_protect/ /opt/app_protect/; do
+ if [ ! -d ${i} ]; then
+ mkdir -p ${i}
+ fi
+ chown -R 101:0 ${i}
+ chmod -R g=u ${i}
+done
+
touch /etc/nginx/waf/nac-usersigs/index.conf
diff --git a/charts/nginx-ingress/README.md b/charts/nginx-ingress/README.md
index 239ed97490..7e44b0933c 100644
--- a/charts/nginx-ingress/README.md
+++ b/charts/nginx-ingress/README.md
@@ -443,6 +443,20 @@ The following tables lists the configurable parameters of the NGINX Ingress Cont
|`controller.pod.annotations` | The annotations of the Ingress Controller pod. | {} |
|`controller.pod.extraLabels` | The additional extra labels of the Ingress Controller pod. | {} |
|`controller.appprotect.enable` | Enables the App Protect WAF module in the Ingress Controller. | false |
+|`controller.appprotect.v5` | Enables App Protect WAF v5. | false |
+|`controller.appprotect.volumes` | Volumes for App Protect WAF v5. | [{"name": "app-protect-bd-config", "emptyDir": {}},{"name": "app-protect-config", "emptyDir": {}},{"name": "app-protect-bundles", "emptyDir": {}}] |
+|`controller.appprotect.enforcer.host` | Host that the App Protect WAF v5 Enforcer runs on. | "127.0.0.1" |
+|`controller.appprotect.enforcer.port` | Port that the App Protect WAF v5 Enforcer runs on. | 50000 |
+|`controller.appprotect.enforcer.image` | The image repository of the App Protect WAF v5 Enforcer. | private-registry.nginx.com/nap/waf-enforcer |
+|`controller.appprotect.enforcer.tag` | The tag of the App Protect WAF v5 Enforcer. | "5.2.0" |
+|`controller.appprotect.enforcer.digest` | The digest of the App Protect WAF v5 Enforcer. Takes precedence over tag if set. | "5.2.0" |
+|`controller.appprotect.enforcer.pullPolicy` | The pull policy for the App Protect WAF v5 Enforcer image. | "5.2.0" |
+|`controller.appprotect.enforcer.securityContext` | The security context for App Protect WAF v5 Enforcer container. | {} |
+|`controller.appprotect.configManager.image` | The image repository of the App Protect WAF v5 Configuration Manager. | private-registry.nginx.com/nap/waf-config-mgr |
+|`controller.appprotect.configManager.tag` | The tag of the App Protect WAF v5 Configuration Manager. | "5.2.0" |
+|`controller.appprotect.configManager.digest` | The digest of the App Protect WAF v5 Configuration Manager. Takes precedence over tag if set. | "5.2.0" |
+|`controller.appprotect.configManager.pullPolicy` | The pull policy for the App Protect WAF v5 Configuration Manager image. | "5.2.0" |
+|`controller.appprotect.configManager.securityContext` | The security context for App Protect WAF v5 Configuration Manager container. | {"allowPrivilegeEscalation":false,"runAsUser":101,"runAsNonRoot":true,"capabilities":{"drop":["all"]}} |
|`controller.appprotectdos.enable` | Enables the App Protect DoS module in the Ingress Controller. | false |
|`controller.appprotectdos.debug` | Enable debugging for App Protect DoS. | false |
|`controller.appprotectdos.maxDaemons` | Max number of ADMD instances. | 1 |
diff --git a/charts/nginx-ingress/templates/_helpers.tpl b/charts/nginx-ingress/templates/_helpers.tpl
index 497e1f6cdb..051cd17b0d 100644
--- a/charts/nginx-ingress/templates/_helpers.tpl
+++ b/charts/nginx-ingress/templates/_helpers.tpl
@@ -152,10 +152,27 @@ Expand wildcard TLS name.
Expand image name.
*/}}
{{- define "nginx-ingress.image" -}}
-{{- if .Values.controller.image.digest -}}
-{{- printf "%s@%s" .Values.controller.image.repository .Values.controller.image.digest -}}
+{{ include "nginx-ingress.image-digest-or-tag" (dict "image" .Values.controller.image "default" .Chart.AppVersion ) }}
+{{- end -}}
+
+{{- define "nap-enforcer.image" -}}
+{{ include "nginx-ingress.image-digest-or-tag" (dict "image" .Values.controller.appprotect.enforcer.image "default" .Chart.AppVersion ) }}
+{{- end -}}
+
+{{- define "nap-config-manager.image" -}}
+{{ include "nginx-ingress.image-digest-or-tag" (dict "image" .Values.controller.appprotect.configManager.image "default" .Chart.AppVersion ) }}
+{{- end -}}
+
+{{/*
+Accepts an image struct like .Values.controller.image along with a default value to use
+if the digest or tag is not set. Can be called like:
+include "nginx-ingress.image-digest-or-tag" (dict "image" .Values.controller.image "default" .Chart.AppVersion
+*/}}
+{{- define "nginx-ingress.image-digest-or-tag" -}}
+{{- if .image.digest -}}
+{{- printf "%s@%s" .image.repository .image.digest -}}
{{- else -}}
-{{- printf "%s:%s" .Values.controller.image.repository (include "nginx-ingress.tag" .) -}}
+{{- printf "%s:%s" .image.repository (default .default .image.tag) -}}
{{- end -}}
{{- end -}}
@@ -198,6 +215,9 @@ Build the args for the service binary.
{{- if and .Values.controller.appprotect.enable .Values.controller.appprotect.logLevel }}
- -app-protect-log-level={{ .Values.controller.appprotect.logLevel }}
{{ end }}
+{{- if and .Values.controller.appprotect.enable .Values.controller.appprotect.v5 }}
+- -app-protect-enforcer-address="{{ .Values.controller.appprotect.enforcer.host | default "127.0.0.1" }}:{{ .Values.controller.appprotect.enforcer.port | default 50000 }}"
+{{- end }}
- -enable-app-protect-dos={{ .Values.controller.appprotectdos.enable }}
{{- if .Values.controller.appprotectdos.enable }}
- -app-protect-dos-debug={{ .Values.controller.appprotectdos.debug }}
@@ -312,6 +332,9 @@ List of volumes for controller.
- name: nginx-log
emptyDir: {}
{{- end }}
+{{- if .Values.controller.appprotect.v5 }}
+{{- toYaml .Values.controller.appprotect.volumes }}
+{{- end }}
{{- if .Values.controller.volumes }}
{{ toYaml .Values.controller.volumes }}
{{- end }}
@@ -361,6 +384,16 @@ volumeMounts:
- mountPath: /var/log/nginx
name: nginx-log
{{- end }}
+{{- if .Values.controller.appprotect.v5 }}
+- name: app-protect-bd-config
+ mountPath: /opt/app_protect/bd_config
+- name: app-protect-config
+ mountPath: /opt/app_protect/config
+ # app-protect-bundles is mounted so that Ingress Controller
+ # can verify that referenced bundles are present
+- name: app-protect-bundles
+ mountPath: /etc/app_protect/bundles
+{{- end }}
{{- if .Values.controller.volumeMounts }}
{{ toYaml .Values.controller.volumeMounts }}
{{- end }}
@@ -378,6 +411,38 @@ volumeMounts:
{{- end -}}
{{- end -}}
+{{- define "nginx-ingress.appprotect.v5" -}}
+{{- if .Values.controller.appprotect.v5}}
+- name: waf-enforcer
+ image: {{ include "nap-enforcer.image" . }}
+ imagePullPolicy: "{{ .Values.controller.appprotect.enforcer.image.pullPolicy }}"
+{{- if .Values.controller.appprotect.enforcer.securityContext }}
+ securityContext:
+{{ toYaml .Values.controller.appprotect.enforcer.securityContext | nindent 6 }}
+{{- end }}
+ env:
+ - name: ENFORCER_PORT
+ value: "{{ .Values.controller.appprotect.enforcer.port | default 50000 }}"
+ volumeMounts:
+ - name: app-protect-bd-config
+ mountPath: /opt/app_protect/bd_config
+- name: waf-config-mgr
+ image: {{ include "nap-config-manager.image" . }}
+ imagePullPolicy: "{{ .Values.controller.appprotect.configManager.image.pullPolicy }}"
+{{- if .Values.controller.appprotect.configManager.securityContext }}
+ securityContext:
+{{ toYaml .Values.controller.appprotect.configManager.securityContext | nindent 6 }}
+{{- end }}
+ volumeMounts:
+ - name: app-protect-bd-config
+ mountPath: /opt/app_protect/bd_config
+ - name: app-protect-config
+ mountPath: /opt/app_protect/config
+ - name: app-protect-bundles
+ mountPath: /etc/app_protect/bundles
+{{- end}}
+{{- end -}}
+
{{- define "nginx-ingress.agentConfiguration" -}}
log:
level: {{ .Values.nginxAgent.logLevel }}
diff --git a/charts/nginx-ingress/templates/controller-daemonset.yaml b/charts/nginx-ingress/templates/controller-daemonset.yaml
index 8da65c4683..268f127f85 100644
--- a/charts/nginx-ingress/templates/controller-daemonset.yaml
+++ b/charts/nginx-ingress/templates/controller-daemonset.yaml
@@ -134,6 +134,9 @@ spec:
{{- if .Values.controller.extraContainers }}
{{ toYaml .Values.controller.extraContainers | nindent 6 }}
{{- end }}
+
+{{- include "nginx-ingress.appprotect.v5" . | nindent 6 }}
+
{{- if or (eq (include "nginx-ingress.readOnlyRootFilesystem" .) "true" ) .Values.controller.initContainers }}
initContainers:
{{- end }}
diff --git a/charts/nginx-ingress/templates/controller-deployment.yaml b/charts/nginx-ingress/templates/controller-deployment.yaml
index c8bc8f833c..95bf3bb165 100644
--- a/charts/nginx-ingress/templates/controller-deployment.yaml
+++ b/charts/nginx-ingress/templates/controller-deployment.yaml
@@ -141,6 +141,9 @@ spec:
{{- if .Values.controller.extraContainers }}
{{ toYaml .Values.controller.extraContainers | nindent 6 }}
{{- end }}
+
+{{- include "nginx-ingress.appprotect.v5" . | nindent 6 }}
+
{{- if or ( eq (include "nginx-ingress.readOnlyRootFilesystem" .) "true" ) .Values.controller.initContainers }}
initContainers:
{{- end }}
diff --git a/charts/nginx-ingress/values.schema.json b/charts/nginx-ingress/values.schema.json
index 4d8f0400c7..d73c968af7 100644
--- a/charts/nginx-ingress/values.schema.json
+++ b/charts/nginx-ingress/values.schema.json
@@ -119,6 +119,15 @@
true
]
},
+ "v5": {
+ "type": "boolean",
+ "default": false,
+ "title": "Enables App Protect WAF v5.",
+ "examples": [
+ false,
+ true
+ ]
+ },
"logLevel": {
"type": "string",
"default": "",
@@ -139,6 +148,201 @@
"debug",
"trace"
]
+ },
+ "volumes": {
+ "type": "array",
+ "default": [
+ {
+ "name": "app-protect-bd-config",
+ "emptyDir": {}
+ },
+ {
+ "name": "app-protect-config",
+ "emptyDir": {}
+ },
+ {
+ "name": "app-protect-bundles",
+ "emptyDir": {}
+ }
+ ],
+ "title": "Volumes for App Protect WAF v5",
+ "items": {
+ "type": "object",
+ "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.29.0/_definitions.json#/definitions/io.k8s.api.core.v1.Volume"
+ }
+ },
+ "enforcer": {
+ "type": "object",
+ "properties": {
+ "host": {
+ "type": "string",
+ "default": "127.0.0.1",
+ "title": "Port which the App Protect WAF v5 Enforcer process runs on",
+ "examples": [
+ "127.0.0.1"
+ ]
+ },
+ "port": {
+ "type": "integer",
+ "default": 50000,
+ "title": "Port which the App Protect WAF v5 Enforcer process runs on",
+ "examples": [
+ 50000
+ ]
+ },
+ "image": {
+ "type": "object",
+ "default": {},
+ "title": "The image Schema",
+ "required": [
+ "repository"
+ ],
+ "properties": {
+ "repository": {
+ "type": "string",
+ "default": "private-registry.nginx.com/nap/waf-enforcer",
+ "title": "The repository of the App Protect WAF v5 Enforcer image",
+ "examples": [
+ "private-registry.nginx.com/nap/waf-enforcer"
+ ]
+ },
+ "tag": {
+ "type": "string",
+ "default": "5.2.0",
+ "title": "The tag of the App Protect WAF v5 Enforcer image",
+ "examples": [
+ "5.2.0"
+ ]
+ },
+ "digest": {
+ "type": "string",
+ "default": "",
+ "title": "The digest of the App Protect WAF v5 Enforcer image",
+ "examples": [
+ "sha256:2710c264e8eaeb663cee63db37b75a1ac1709f63a130fb091c843a6c3a4dc572"
+ ]
+ },
+ "pullPolicy": {
+ "type": "string",
+ "default": "IfNotPresent",
+ "title": "The pullPolicy for the App Protect WAF v5 Enforcer image",
+ "allOf": [
+ {
+ "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.29.0/_definitions.json#/definitions/io.k8s.api.core.v1.Container/properties/imagePullPolicy"
+ },
+ {
+ "enum": [
+ "Always",
+ "IfNotPresent",
+ "Never"
+ ]
+ }
+ ],
+ "examples": [
+ "Always",
+ "IfNotPresent",
+ "Never"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "repository": "private-registry.nginx.com/nap/waf-enforcer",
+ "tag": "5.2.0",
+ "pullPolicy": "IfNotPresent"
+ }
+ ]
+ },
+ "securityContext": {
+ "type": "object",
+ "default": {},
+ "title": "The securityContext Schema",
+ "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.29.0/_definitions.json#/definitions/io.k8s.api.core.v1.SecurityContext"
+ }
+ }
+ },
+ "configManager": {
+ "type": "object",
+ "properties": {
+ "image": {
+ "type": "object",
+ "default": {},
+ "title": "The image Schema",
+ "required": [
+ "repository"
+ ],
+ "properties": {
+ "repository": {
+ "type": "string",
+ "default": "private-registry.nginx.com/nap/waf-config-mgr",
+ "title": "The repository of the App Protect WAF v5 Config Manager image",
+ "examples": [
+ "private-registry.nginx.com/nap/waf-config-mgr"
+ ]
+ },
+ "tag": {
+ "type": "string",
+ "default": "5.2.0",
+ "title": "The tag of the App Protect WAF v5 Config Manager image",
+ "examples": [
+ "5.2.0"
+ ]
+ },
+ "digest": {
+ "type": "string",
+ "default": "",
+ "title": "The digest of the App Protect WAF v5 Config Manager image",
+ "examples": [
+ "sha256:2710c264e8eaeb663cee63db37b75a1ac1709f63a130fb091c843a6c3a4dc572"
+ ]
+ },
+ "pullPolicy": {
+ "type": "string",
+ "default": "IfNotPresent",
+ "title": "The pullPolicy for the App Protect WAF v5 Config Manager image",
+ "allOf": [
+ {
+ "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.29.0/_definitions.json#/definitions/io.k8s.api.core.v1.Container/properties/imagePullPolicy"
+ },
+ {
+ "enum": [
+ "Always",
+ "IfNotPresent",
+ "Never"
+ ]
+ }
+ ],
+ "examples": [
+ "Always",
+ "IfNotPresent",
+ "Never"
+ ]
+ }
+ },
+ "examples": [
+ {
+ "repository": "private-registry.nginx.com/nap/waf-config-mgr",
+ "tag": "5.2.0",
+ "pullPolicy": "IfNotPresent"
+ }
+ ]
+ },
+ "securityContext": {
+ "type": "object",
+ "default": {
+ "allowPrivilegeEscalation": false,
+ "runAsUser": 101,
+ "runAsNonRoot": true,
+ "capabilities": {
+ "drop": [
+ "all"
+ ]
+ }
+ },
+ "title": "The securityContext Schema",
+ "$ref": "https://raw.githubusercontent.com/nginxinc/kubernetes-json-schema/master/v1.29.0/_definitions.json#/definitions/io.k8s.api.core.v1.SecurityContext"
+ }
+ }
}
},
"examples": [
diff --git a/charts/nginx-ingress/values.yaml b/charts/nginx-ingress/values.yaml
index 3e10e200c7..ea91a10a12 100644
--- a/charts/nginx-ingress/values.yaml
+++ b/charts/nginx-ingress/values.yaml
@@ -21,9 +21,65 @@ controller:
appprotect:
## Enable the App Protect WAF module in the Ingress Controller.
enable: false
+ ## Enables App Protect WAF v5.
+ v5: false
## Sets log level for App Protect WAF. Allowed values: fatal, error, warn, info, debug, trace
# logLevel: fatal
+ # Volumes for App Protect WAF v5
+ # Required volumes are: app-protect-bd-config, app-protect-config, and app-protect-bundles
+ volumes:
+ - name: app-protect-bd-config
+ emptyDir: {}
+ - name: app-protect-config
+ emptyDir: {}
+ - name: app-protect-bundles
+ emptyDir: {}
+
+ ## Configuration for App Protect WAF v5 Enforcer
+ enforcer:
+ # Host that the App Protect WAF v5 Enforcer runs on.
+ # This will normally be "127.0.0.1" as the Enforcer container
+ # will run in the same pod as the Ingress Controller container.
+ host: "127.0.0.1"
+ # Port that the App Protect WAF v5 Enforcer runs on.
+ port: 50000
+ image:
+ ## The image repository of the App Protect WAF v5 Enforcer.
+ repository: private-registry.nginx.com/nap/waf-enforcer
+
+ ## The tag of the App Protect WAF v5 Enforcer image.
+ tag: "5.2.0"
+ ## The digest of the App Protect WAF v5 Enforcer image.
+ ## If digest is specified it has precedence over tag and will be used instead
+ # digest: "sha256:CHANGEME"
+
+ ## The pull policy for the App Protect WAF v5 Enforcer image.
+ pullPolicy: IfNotPresent
+ securityContext: {}
+
+ ## Configuration for App Protect WAF v5 Configuration Manager
+ configManager:
+ image:
+ ## The image repository of the App Protect WAF v5 Configuration Manager.
+ repository: private-registry.nginx.com/nap/waf-config-mgr
+
+ ## The tag of the App Protect WAF v5 Configuration Manager image.
+ tag: "5.2.0"
+ ## The digest of the App Protect WAF v5 Configuration Manager image.
+ ## If digest is specified it has precedence over tag and will be used instead
+ # digest: "sha256:CHANGEME"
+
+ ## The pull policy for the App Protect WAF v5 Configuration Manager image.
+ pullPolicy: IfNotPresent
+ securityContext:
+ allowPrivilegeEscalation: false
+ runAsUser: 101 #nginx
+ runAsNonRoot: true
+ capabilities:
+ drop:
+ - all
+
## Support for App Protect DoS
appprotectdos:
## Enable the App Protect DoS module in the Ingress Controller.
@@ -173,7 +229,8 @@ controller:
type: RuntimeDefault
## The security context for the Ingress Controller containers.
- securityContext: {} # Remove curly brackets before adding values
+ securityContext:
+ {} # Remove curly brackets before adding values
# allowPrivilegeEscalation: true
# readOnlyRootFilesystem: true
# runAsUser: 101 #nginx
diff --git a/cmd/nginx-ingress/flags.go b/cmd/nginx-ingress/flags.go
index 3d02c86b23..d36381974e 100644
--- a/cmd/nginx-ingress/flags.go
+++ b/cmd/nginx-ingress/flags.go
@@ -16,8 +16,10 @@ import (
)
const (
- dynamicSSLReloadParam = "ssl-dynamic-reload"
- dynamicWeightChangesParam = "weight-changes-dynamic-reload"
+ dynamicSSLReloadParam = "ssl-dynamic-reload"
+ dynamicWeightChangesParam = "weight-changes-dynamic-reload"
+ appProtectLogLevelDefault = "fatal"
+ appProtectEnforcerAddrDefault = "127.0.0.1:50000"
)
var (
@@ -65,6 +67,9 @@ var (
appProtectDosMaxWorkers = flag.Int("app-protect-dos-max-workers", 0, "Max number of nginx processes to support. Requires -nginx-plus and -enable-app-protect-dos.")
appProtectDosMemory = flag.Int("app-protect-dos-memory", 0, "RAM memory size to consume in MB. Requires -nginx-plus and -enable-app-protect-dos.")
+ appProtectEnforcerAddress = flag.String("app-protect-enforcer-address", appProtectEnforcerAddrDefault,
+ `Sets address for App Protect v5 Enforcer. Requires -nginx-plus and -enable-app-protect.`)
+
agent = flag.Bool("agent", false, "Enable NGINX Agent")
agentInstanceGroup = flag.String("agent-instance-group", "nginx-ingress-controller", "Grouping used to associate NGINX Ingress Controller instances")
@@ -440,8 +445,6 @@ func validatePort(port int) error {
return nil
}
-const appProtectLogLevelDefault = "fatal"
-
// validateAppProtectLogLevel makes sure a given logLevel is one of the allowed values
func validateAppProtectLogLevel(logLevel string) error {
switch strings.ToLower(logLevel) {
diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go
index db38de9bd5..d911d2f818 100644
--- a/cmd/nginx-ingress/main.go
+++ b/cmd/nginx-ingress/main.go
@@ -7,6 +7,7 @@ import (
"net/http"
"os"
"os/signal"
+ "regexp"
"runtime"
"strings"
"syscall"
@@ -47,11 +48,13 @@ var (
)
const (
- nginxVersionLabel = "app.nginx.org/version"
- versionLabel = "app.kubernetes.io/version"
- appProtectVersionLabel = "appprotect.f5.com/version"
- agentVersionLabel = "app.nginx.org/agent-version"
- appProtectVersionPath = "/opt/app_protect/RELEASE"
+ nginxVersionLabel = "app.nginx.org/version"
+ versionLabel = "app.kubernetes.io/version"
+ appProtectVersionLabel = "appprotect.f5.com/version"
+ agentVersionLabel = "app.nginx.org/agent-version"
+ appProtectVersionPath = "/opt/app_protect/RELEASE"
+ appProtectv4BundleFolder = "/etc/nginx/waf/bundles/"
+ appProtectv5BundleFolder = "/etc/app_protect/bundles/"
)
func main() {
@@ -80,8 +83,16 @@ func main() {
nginxVersion := getNginxVersionInfo(nginxManager)
var appProtectVersion string
+ var appProtectV5 bool
+ appProtectBundlePath := appProtectv4BundleFolder
if *appProtect {
appProtectVersion = getAppProtectVersionInfo()
+
+ r := regexp.MustCompile("^5.*")
+ if r.MatchString(appProtectVersion) {
+ appProtectV5 = true
+ appProtectBundlePath = appProtectv5BundleFolder
+ }
}
var agentVersion string
@@ -119,7 +130,9 @@ func main() {
EnableSnippets: *enableSnippets,
NginxServiceMesh: *spireAgentAddress != "",
MainAppProtectLoadModule: *appProtect,
+ MainAppProtectV5LoadModule: appProtectV5,
MainAppProtectDosLoadModule: *appProtectDos,
+ MainAppProtectV5EnforcerAddr: *appProtectEnforcerAddress,
EnableLatencyMetrics: *enableLatencyMetrics,
EnableOIDC: *enableOIDC,
SSLRejectHandshake: sslRejectHandshake,
@@ -128,6 +141,7 @@ func main() {
DynamicWeightChangesReload: *enableDynamicWeightChangesReload,
StaticSSLPath: nginxManager.GetSecretsDir(),
NginxVersion: nginxVersion,
+ AppProtectBundlePath: appProtectBundlePath,
}
processNginxConfig(staticCfgParams, cfgParams, templateExecutor, nginxManager)
@@ -137,7 +151,7 @@ func main() {
nginxManager.CreateTLSPassthroughHostsConfig(emptyFile)
}
- process := startChildProcesses(nginxManager)
+ process := startChildProcesses(nginxManager, appProtectV5)
plusClient := createPlusClient(*nginxPlus, useFakeNginxManager, nginxManager)
@@ -456,10 +470,11 @@ type childProcesses struct {
// newChildProcesses starts the several child processes based on flags set.
// AppProtect. AppProtectDos, Agent.
-func startChildProcesses(nginxManager nginx.Manager) childProcesses {
+func startChildProcesses(nginxManager nginx.Manager, appProtectV5 bool) childProcesses {
var aPPluginDone chan error
- if *appProtect {
+ // Do not start AppProtect Plugins when using v5.
+ if *appProtect && !appProtectV5 {
aPPluginDone = make(chan error, 1)
nginxManager.AppProtectPluginStart(aPPluginDone, *appProtectLogLevel)
}
diff --git a/internal/configs/config_params.go b/internal/configs/config_params.go
index ce011400bc..be86ae4eb9 100644
--- a/internal/configs/config_params.go
+++ b/internal/configs/config_params.go
@@ -145,7 +145,9 @@ type StaticConfigParams struct {
NginxServiceMesh bool
EnableInternalRoutes bool
MainAppProtectLoadModule bool
+ MainAppProtectV5LoadModule bool
MainAppProtectDosLoadModule bool
+ MainAppProtectV5EnforcerAddr string
InternalRouteServerName string
EnableLatencyMetrics bool
EnableOIDC bool
@@ -155,6 +157,7 @@ type StaticConfigParams struct {
StaticSSLPath string
DynamicWeightChangesReload bool
NginxVersion nginx.Version
+ AppProtectBundlePath string
}
// GlobalConfigParams holds global configuration parameters. For now, it only holds listeners.
diff --git a/internal/configs/configmaps.go b/internal/configs/configmaps.go
index fbcd63b68d..c4041336da 100644
--- a/internal/configs/configmaps.go
+++ b/internal/configs/configmaps.go
@@ -565,7 +565,9 @@ func GenerateNginxMainConfig(staticCfgParams *StaticConfigParams, config *Config
VariablesHashBucketSize: config.VariablesHashBucketSize,
VariablesHashMaxSize: config.VariablesHashMaxSize,
AppProtectLoadModule: staticCfgParams.MainAppProtectLoadModule,
+ AppProtectV5LoadModule: staticCfgParams.MainAppProtectV5LoadModule,
AppProtectDosLoadModule: staticCfgParams.MainAppProtectDosLoadModule,
+ AppProtectV5EnforcerAddr: staticCfgParams.MainAppProtectV5EnforcerAddr,
AppProtectFailureModeAction: config.MainAppProtectFailureModeAction,
AppProtectCompressedRequestsAction: config.MainAppProtectCompressedRequestsAction,
AppProtectCookieSeed: config.MainAppProtectCookieSeed,
diff --git a/internal/configs/configurator.go b/internal/configs/configurator.go
index 080f597ceb..d8412b8bba 100644
--- a/internal/configs/configurator.go
+++ b/internal/configs/configurator.go
@@ -31,7 +31,6 @@ import (
const (
pemFileNameForWildcardTLSSecret = "/etc/nginx/secrets/wildcard" // #nosec G101
- appProtectBundleFolder = "/etc/nginx/waf/bundles/"
appProtectPolicyFolder = "/etc/nginx/waf/nac-policies/"
appProtectLogConfFolder = "/etc/nginx/waf/nac-logconfs/"
appProtectUserSigFolder = "/etc/nginx/waf/nac-usersigs/"
diff --git a/internal/configs/version1/config.go b/internal/configs/version1/config.go
index c05edceb55..85d8c2006a 100644
--- a/internal/configs/version1/config.go
+++ b/internal/configs/version1/config.go
@@ -245,6 +245,8 @@ type MainConfig struct {
WorkerRlimitNofile string
WorkerShutdownTimeout string
AppProtectLoadModule bool
+ AppProtectV5LoadModule bool
+ AppProtectV5EnforcerAddr string
AppProtectFailureModeAction string
AppProtectCompressedRequestsAction string
AppProtectCookieSeed string
diff --git a/internal/configs/version1/nginx-plus.tmpl b/internal/configs/version1/nginx-plus.tmpl
index e525a533c6..e13589d5b3 100644
--- a/internal/configs/version1/nginx-plus.tmpl
+++ b/internal/configs/version1/nginx-plus.tmpl
@@ -85,6 +85,10 @@ http {
{{- end}}
{{- end}}
+ {{- if .AppProtectV5LoadModule}}
+ app_protect_enforcer_address {{ .AppProtectV5EnforcerAddr }};
+ {{- end}}
+
{{- if .AccessLogOff}}
access_log off;
{{- else}}
diff --git a/internal/configs/version2/templates_test.go b/internal/configs/version2/templates_test.go
index 83e75cade0..28ea24e599 100644
--- a/internal/configs/version2/templates_test.go
+++ b/internal/configs/version2/templates_test.go
@@ -2705,7 +2705,7 @@ var (
VerifyDepth: 2,
},
WAF: &WAF{
- ApBundle: "/etc/nginx/waf/bundles/NginxDefaultPolicy.tgz",
+ ApBundle: "/fake/bundle/path/NginxDefaultPolicy.tgz",
ApSecurityLogEnable: true,
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf"},
},
diff --git a/internal/configs/virtualserver.go b/internal/configs/virtualserver.go
index aa6c12fcdf..64e819bfda 100644
--- a/internal/configs/virtualserver.go
+++ b/internal/configs/virtualserver.go
@@ -315,7 +315,7 @@ func newVirtualServerConfigurator(
bundleValidator bundleValidator,
) *virtualServerConfigurator {
if bundleValidator == nil {
- bundleValidator = newInternalBundleValidator(appProtectBundleFolder)
+ bundleValidator = newInternalBundleValidator(staticParams.AppProtectBundlePath)
}
return &virtualServerConfigurator{
cfgParams: cfgParams,
@@ -1325,7 +1325,6 @@ func (p *policiesCfg) addWAFConfig(
}
if waf.ApBundle != "" {
- p.WAF.ApBundle = appProtectBundleFolder + waf.ApBundle
bundlePath, err := p.BundleValidator.validate(waf.ApBundle)
if err != nil {
res.addWarningf("WAF policy %s references an invalid or non-existing App Protect bundle %s", polKey, bundlePath)
diff --git a/internal/configs/virtualserver_test.go b/internal/configs/virtualserver_test.go
index a7f89270db..22cc242b48 100644
--- a/internal/configs/virtualserver_test.go
+++ b/internal/configs/virtualserver_test.go
@@ -6378,7 +6378,7 @@ func TestGeneratePolicies_GeneratesWAFPolicyOnValidApBundle(t *testing.T) {
want: policiesCfg{
WAF: &version2.WAF{
Enable: "on",
- ApBundle: "/etc/nginx/waf/bundles/testWAFPolicyBundle.tgz",
+ ApBundle: "/fake/bundle/path/testWAFPolicyBundle.tgz",
},
},
},
@@ -6410,9 +6410,9 @@ func TestGeneratePolicies_GeneratesWAFPolicyOnValidApBundle(t *testing.T) {
want: policiesCfg{
WAF: &version2.WAF{
Enable: "on",
- ApBundle: "/etc/nginx/waf/bundles/testWAFPolicyBundle.tgz",
+ ApBundle: "/fake/bundle/path/testWAFPolicyBundle.tgz",
ApSecurityLogEnable: true,
- ApLogConf: []string{"/etc/nginx/waf/bundles/secops_dashboard.tgz syslog:server=localhost:514"},
+ ApLogConf: []string{"/fake/bundle/path/secops_dashboard.tgz syslog:server=localhost:514"},
},
},
},
@@ -14663,7 +14663,7 @@ var (
type fakeBundleValidator struct{}
func (*fakeBundleValidator) validate(bundle string) (string, error) {
- bundle = fmt.Sprintf("/etc/nginx/waf/bundles/%s", bundle)
+ bundle = fmt.Sprintf("/fake/bundle/path/%s", bundle)
if strings.Contains(bundle, "invalid") {
return bundle, fmt.Errorf("invalid bundle %s", bundle)
}
From 580940a3cab7c8cf30928cf40d83a9d0301be8cf Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 13 Jun 2024 13:20:08 +0100
Subject: [PATCH 11/38] Bump github/codeql-action from 3.25.8 to 3.25.9 in the
actions group (#5739)
---
.github/workflows/build-oss.yml | 2 +-
.github/workflows/build-plus.yml | 2 +-
.github/workflows/codeql-analysis.yml | 6 +++---
.github/workflows/scorecards.yml | 2 +-
4 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index fea450ab15..6e3e912565 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -185,7 +185,7 @@ jobs:
if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Upload Trivy scan results to GitHub Security tab
- uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
+ uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
continue-on-error: true
with:
sarif_file: "trivy-results-${{ inputs.image }}.sarif"
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index e689efc1d2..e30093685f 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -212,7 +212,7 @@ jobs:
if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
- name: Upload Trivy scan results to GitHub Security tab
- uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
+ uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
continue-on-error: true
with:
sarif_file: "trivy-results-${{ inputs.image }}.sarif"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 93f3431c7e..29163d9c43 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -70,7 +70,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
+ uses: github/codeql-action/init@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -89,7 +89,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
+ uses: github/codeql-action/autobuild@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -102,6 +102,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
+ uses: github/codeql-action/analyze@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
with:
category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index 03237e4d47..9ef12bab55 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -57,6 +57,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
- uses: github/codeql-action/upload-sarif@2e230e8fe0ad3a14a340ad0815ddb96d599d2aff # v3.25.8
+ uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
with:
sarif_file: results.sarif
From bf146cde87db78cf186d296fcafe77e5d9e40f11 Mon Sep 17 00:00:00 2001
From: oseoin
Date: Thu, 13 Jun 2024 15:07:09 +0100
Subject: [PATCH 12/38] Mount config and deployments dirs to smoke containers
(#5740)
---
.github/actions/smoke-tests/action.yaml | 2 ++
internal/k8s/controller.go | 17 ++++++++++-------
tests/Makefile | 2 ++
3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/.github/actions/smoke-tests/action.yaml b/.github/actions/smoke-tests/action.yaml
index a85aba1415..e0a02ca534 100644
--- a/.github/actions/smoke-tests/action.yaml
+++ b/.github/actions/smoke-tests/action.yaml
@@ -62,6 +62,8 @@ runs:
--name test-runner-${{ github.run_id }} \
--network=kind \
-v ${{ github.workspace }}/tests:/workspace/tests \
+ -v ${{ github.workspace }}/deployments:/workspace/deployments \
+ -v ${{ github.workspace }}/config:/workspace/config \
-v ~/.kube/kind/config:/root/.kube/config ${{ inputs.test-image }} \
--context=kind-${{ github.run_id }} \
--image=${{ inputs.image-name }}:${{ inputs.tag }} \
diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go
index a4a5f4d499..9e2aec26f6 100644
--- a/internal/k8s/controller.go
+++ b/internal/k8s/controller.go
@@ -944,15 +944,18 @@ func (lbc *LoadBalancerController) updateNumberOfIngressControllerReplicas(contr
}
// handle virtualservers
- resources = lbc.findVirtualServersUsingRatelimitScaling()
- resourceExes = lbc.createExtendedResources(resources)
- for _, vserver := range resourceExes.VirtualServerExes {
- found = true
- _, err := lbc.configurator.AddOrUpdateVirtualServer(vserver)
- if err != nil {
- glog.Errorf("Error updating ratelimit for VirtualServer %s/%s: %s", vserver.VirtualServer.Namespace, vserver.VirtualServer.Name, err)
+ if lbc.areCustomResourcesEnabled {
+ resources = lbc.findVirtualServersUsingRatelimitScaling()
+ resourceExes = lbc.createExtendedResources(resources)
+ for _, vserver := range resourceExes.VirtualServerExes {
+ found = true
+ _, err := lbc.configurator.AddOrUpdateVirtualServer(vserver)
+ if err != nil {
+ glog.Errorf("Error updating ratelimit for VirtualServer %s/%s: %s", vserver.VirtualServer.Namespace, vserver.VirtualServer.Name, err)
+ }
}
}
+
}
return found
}
diff --git a/tests/Makefile b/tests/Makefile
index 28c3f58bf1..6e24864055 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -55,6 +55,8 @@ run-tests-in-kind: ## Run tests in Kind
docker run --network=kind --rm \
-v $(KIND_KUBE_CONFIG_FOLDER):/root/.kube \
-v $(ROOT_DIR)/tests:/workspace/tests \
+ -v $(ROOT_DIR)/deployments:/workspace/deployments \
+ -v $(ROOT_DIR)/config:/workspace/config \
$(TEST_PREFIX):$(TEST_TAG) \
--context=kind-$(strip $(K8S_CLUSTER_NAME)) \
--image=$(BUILD_IMAGE) --image-pull-policy=$(PULL_POLICY) \
From f4d416815c14ca64386c7d67b8f86ba27ccc09bc Mon Sep 17 00:00:00 2001
From: Alan Dooley
Date: Thu, 13 Jun 2024 15:44:45 +0100
Subject: [PATCH 13/38] Add F5 prefix to configuration opening paragraphs,
style consistency (#5737)
Add F5 prefix to configuration opening paragraphs, style consistency
This commit changes each of the opening paragraphs of the Configuration
section to ensure they have the F5 prefixed name for the first instance
of NGINX Ingress Controller.
It also includes a large amount of other changes:
- Relative links
- Erroneous product names ("the Ingress Controller")
- Contemporary table formatting
- Updated and decoupled input/output code blocks
- Sentence case for page titles and headings
- Small contextual rewrites
- Updated links to appropriate tags
A small number of unrelated changes were also included, regarding NGINX
App Protect and a small typo in a command line option.
Signed-off-by: Alan Dooley
Co-authored-by: Venktesh Shivam Patel
---
.../configuration/configuration-examples.md | 4 +-
.../global-configuration/_index.md | 4 +-
.../command-line-arguments.md | 156 +++++++++--
.../configmap-resource.md | 252 ++++++++++--------
.../global-configuration/custom-templates.md | 6 +-
.../globalconfiguration-resource.md | 81 +++---
.../reporting-resources-status.md | 113 ++++----
...ons.md => host-and-listener-collisions.md} | 79 ++++--
.../configuration/ingress-resources/_index.md | 4 +-
...advanced-configuration-with-annotations.md | 209 +++++++--------
.../advanced-configuration-with-snippets.md | 57 ++--
.../ingress-resources/basic-configuration.md | 38 +--
.../cross-namespace-configuration.md | 6 +-
.../ingress-resources/custom-annotations.md | 8 +-
docs/content/configuration/policy-resource.md | 4 +-
docs/content/configuration/security.md | 17 +-
.../configuration/transportserver-resource.md | 114 ++++----
...server-and-virtualserverroute-resources.md | 233 ++++++++--------
.../app-protect-waf/installation.md | 9 +-
19 files changed, 795 insertions(+), 599 deletions(-)
rename docs/content/configuration/{handling-host-and-listener-collisions.md => host-and-listener-collisions.md} (53%)
diff --git a/docs/content/configuration/configuration-examples.md b/docs/content/configuration/configuration-examples.md
index 3b74c7d85a..aa65bacad6 100644
--- a/docs/content/configuration/configuration-examples.md
+++ b/docs/content/configuration/configuration-examples.md
@@ -2,9 +2,9 @@
docs: DOCS-584
doctypes:
- ''
-title: Configuration Examples
+title: Configuration examples
toc: true
-weight: 2000
+weight: 400
---
Our [GitHub repo](https://github.com/nginxinc/kubernetes-ingress) includes a number of configuration examples:
diff --git a/docs/content/configuration/global-configuration/_index.md b/docs/content/configuration/global-configuration/_index.md
index f2b919eb4c..4f71e2f5f4 100644
--- a/docs/content/configuration/global-configuration/_index.md
+++ b/docs/content/configuration/global-configuration/_index.md
@@ -1,7 +1,7 @@
---
-title: Global Configuration
+title: Global configuration
description:
-weight: 1400
+weight: 100
menu:
docs:
parent: NGINX Ingress Controller
diff --git a/docs/content/configuration/global-configuration/command-line-arguments.md b/docs/content/configuration/global-configuration/command-line-arguments.md
index 973a80e73c..377ea9ea6b 100644
--- a/docs/content/configuration/global-configuration/command-line-arguments.md
+++ b/docs/content/configuration/global-configuration/command-line-arguments.md
@@ -2,15 +2,15 @@
docs: DOCS-585
doctypes:
- ''
-title: Command-line Arguments
+title: Command-line arguments
toc: true
-weight: 1700
+weight: 100
---
-NGINX Ingress Controller supports several command-line arguments, which are passed to it based on your installation method:
+F5 NGINX Ingress Controller supports several command-line arguments, which are set based on installation method:
-- If you're using *Kubernetes Manifests* (Deployment or DaemonSet) to install NGINX Ingress Controller, modify the Manifests to set the command-line arguments. Read [Installation with Manifests]({{}}) for more information.
-- If you're using *Helm* to install NGINX Ingress Controller, modify the parameters of the Helm chart to set the command-line arguments. Read [Installation with Helm]({{}}) documentation for more information.
+- If you're using *Kubernetes Manifests* to install NGINX Ingress Controller, modify the Manifests to set the command-line arguments. View the [Installation with Manifests]({{}}) topic for more information.
+- If you're using *Helm* to install NGINX Ingress Controller, modify the parameters of the Helm chart to set the command-line arguments. View the [Installation with Helm]({{}}) topic for more information.
@@ -22,6 +22,8 @@ Default `false`.
+---
+
### -default-server-tls-secret ``
Secret with a TLS certificate and key for TLS termination of the default server.
@@ -34,18 +36,21 @@ Format: `/`
+---
+
### -wildcard-tls-secret ``
A Secret with a TLS certificate and key for TLS termination of every Ingress/VirtualServer host for which TLS termination is enabled but the Secret is not specified.
-- If the argument is not set, for such Ingress/VirtualServer hosts NGINX will break any attempt to establish a TLS connection.
-
+- If the argument is not set, for such Ingress/VirtualServer hosts NGINX will break any attempt to establish a TLS connection
- If the argument is set, but NGINX Ingress Controller is not able to fetch the Secret from Kubernetes API, NGINX Ingress Controller will fail to start.
Format: `/`
+---
+
### -enable-custom-resources
Enables custom resources.
@@ -54,6 +59,8 @@ Default `true`.
+---
+
### -enable-preview-policies
Enables preview policies. This flag is deprecated. To enable OIDC Policies please use [-enable-oidc](#cmdoption-enable-oidc) instead.
@@ -62,6 +69,8 @@ Default `false`.
+---
+
### -enable-oidc
Enables OIDC policies.
@@ -70,13 +79,17 @@ Default `false`.
-### -inlcude-year
+---
+
+### -include-year
Adds year to log headers.
Default `false`.
-**NOTE**: This flag will be removed in release 2.7 and the year will be included by default.
+{{< note >}} This flag will be removed in release 3.7 and the year will be included by default. {{< /note >}}
+
+---
### -enable-leader-election
@@ -87,6 +100,8 @@ See [-report-ingress-status](#cmdoption-report-ingress-status) flag.
+---
+
### -enable-tls-passthrough
Enable TLS Passthrough on port 443.
@@ -95,6 +110,8 @@ Requires [-enable-custom-resources](#cmdoption-enable-custom-resources).
+---
+
### -tls-passthrough-port ``
Set the port for TLS Passthrough.
@@ -104,6 +121,8 @@ Requires [-enable-custom-resources](#cmdoption-enable-custom-resources).
+---
+
### -enable-cert-manager
Enable x509 automated certificate management for VirtualServer resources using cert-manager (cert-manager.io).
@@ -112,6 +131,8 @@ Requires [-enable-custom-resources](#cmdoption-enable-custom-resources).
+---
+
### -enable-external-dns
Enable integration with ExternalDNS for configuring public DNS entries for VirtualServer resources using [ExternalDNS](https://github.com/kubernetes-sigs/external-dns).
@@ -119,6 +140,8 @@ Enable integration with ExternalDNS for configuring public DNS entries for Virtu
Requires [-enable-custom-resources](#cmdoption-enable-custom-resources).
+---
+
### -external-service ``
Specifies the name of the service with the type LoadBalancer through which the NGINX Ingress Controller pods are exposed externally. The external address of the service is used when reporting the status of Ingress, VirtualServer and VirtualServerRoute resources.
@@ -127,6 +150,8 @@ For Ingress resources only: Requires [-report-ingress-status](#cmdoption-report-
+---
+
### -ingresslink ``
Specifies the name of the IngressLink resource, which exposes the NGINX Ingress Controller pods via a BIG-IP system. The IP of the BIG-IP system is used when reporting the status of Ingress, VirtualServer and VirtualServerRoute resources.
@@ -135,6 +160,8 @@ For Ingress resources only: Requires [-report-ingress-status](#cmdoption-report-
+---
+
### -global-configuration ``
A GlobalConfiguration resource for global configuration of NGINX Ingress Controller.
@@ -145,6 +172,8 @@ Requires [-enable-custom-resources](#cmdoption-enable-custom-resources).
+---
+
### -health-status
Adds a location "/nginx-health" to the default server. The location responds with the 200 status code for any request.
@@ -153,12 +182,16 @@ Useful for external health-checking of NGINX Ingress Controller.
+---
+
### -health-status-uri ``
Sets the URI of health status location in the default server. Requires [-health-status](#cmdoption-health-status). (default `/nginx-health`)
+---
+
### -ingress-class ``
The `-ingress-class` argument refers to the name of the resource `kind: IngressClass`. An IngressClass resource with a name equal to the class must be deployed. Otherwise, NGINX Ingress Controller will fail to start.
@@ -168,12 +201,16 @@ Default `nginx`.
+---
+
### -ingress-template-path ``
Path to the ingress NGINX configuration template for an ingress resource. Default for NGINX is `nginx.ingress.tmpl`; default for NGINX Plus is `nginx-plus.ingress.tmpl`.
+---
+
### -leader-election-lock-name ``
Specifies the name of the ConfigMap, within the same namespace as the controller, used as the lock for leader election.
@@ -182,12 +219,16 @@ Requires [-enable-leader-election](#cmdoption-enable-leader-election).
+---
+
### -log_backtrace_at ``
When logging hits line `file:N`, emit a stack trace.
+---
+
### -main-template-path ``
Path to the main NGINX configuration template.
@@ -197,6 +238,8 @@ Path to the main NGINX configuration template.
+---
+
### -nginx-configmaps ``
A ConfigMap resource for customizing NGINX configuration. If a ConfigMap is set, but NGINX Ingress Controller is not able to fetch it from Kubernetes API, NGINX Ingress Controller will fail to start.
@@ -205,18 +248,24 @@ Format: `/`
+---
+
### -nginx-debug
Enable debugging for NGINX. Uses the nginx-debug binary. Requires 'error-log-level: debug' in the ConfigMap.
+---
+
### -nginx-plus
Enable support for NGINX Plus.
+---
+
### -nginx-reload-timeout ``
Timeout in milliseconds which NGINX Ingress Controller will wait for a successful NGINX reload after a change or at the initial start.
@@ -225,6 +274,8 @@ Default is 60000.
+---
+
### -nginx-status
Enable the NGINX stub_status, or the NGINX Plus API.
@@ -233,6 +284,8 @@ Default `true`.
+---
+
### -nginx-status-allow-cidrs ``
Add IP/CIDR blocks to the allow list for NGINX stub_status or the NGINX Plus API.
@@ -241,6 +294,8 @@ Separate multiple IP/CIDR by commas. (default `127.0.0.1,::1`)
+---
+
### -nginx-status-port ``
Set the port where the NGINX stub_status or the NGINX Plus API is exposed.
@@ -249,14 +304,20 @@ Format: `[1024 - 65535]` (default `8080`)
+---
+
### -proxy ``
-Use a proxy server to connect to Kubernetes API started by "kubectl proxy" command. **For testing purposes only**.
+{{< warning >}} This argument is intended for testing purposes only. {{< /warning >}}
+
+Use a proxy server to connect to Kubernetes API started with `kubectl proxy`.
NGINX Ingress Controller does not start NGINX and does not write any generated NGINX configuration files to disk.
+---
+
### -report-ingress-status
Updates the address field in the status of Ingress resources.
@@ -265,6 +326,8 @@ Requires the [-external-service](#cmdoption-external-service) or [-ingresslink](
+---
+
### -transportserver-template-path ``
Path to the TransportServer NGINX configuration template for a TransportServer resource.
@@ -272,21 +335,26 @@ Path to the TransportServer NGINX configuration template for a TransportServer r
- Default for NGINX is `nginx.transportserver.tmpl`.
- Default for NGINX Plus is `nginx-plus.transportserver.tmpl`.
-
+---
+
### -v ``
Log level for V logs.
+---
+
### -version
Print the version, git-commit hash and build date and exit.
+---
+
### -virtualserver-template-path ``
Path to the VirtualServer NGINX configuration template for a VirtualServer resource.
@@ -297,36 +365,48 @@ Path to the VirtualServer NGINX configuration template for a VirtualServer resou
+---
+
### -vmodule ``
A comma-separated list of pattern=N settings for file-filtered logging.
+---
+
### -watch-namespace ``
Comma separated list of namespaces NGINX Ingress Controller should watch for resources. By default NGINX Ingress Controller watches all namespaces. Mutually exclusive with "watch-namespace-label".
+---
+
### -watch-namespace-label ``
Configures NGINX Ingress Controller to watch only those namespaces with label foo=bar. By default NGINX Ingress Controller watches all namespaces. Mutually exclusive with "watch-namespace".
+---
+
### -watch-secret-namespace ``
Comma separated list of namespaces NGINX Ingress Controller should watch for secrets. If this arg is not configured, NGINX Ingress Controller watches the same namespaces for all resources. See "watch-namespace" and "watch-namespace-label".
+---
+
### -enable-prometheus-metrics
Enables exposing NGINX or NGINX Plus metrics in the Prometheus format.
+---
+
### -prometheus-metrics-listen-port ``
Sets the port where the Prometheus metrics are exposed.
@@ -335,6 +415,8 @@ Format: `[1024 - 65535]` (default `9113`)
+---
+
### -prometheus-tls-secret ``
A Secret with a TLS certificate and key for TLS termination of the Prometheus metrics endpoint.
@@ -344,12 +426,16 @@ A Secret with a TLS certificate and key for TLS termination of the Prometheus me
+---
+
### -enable-service-insight
Exposes the Service Insight endpoint for Ingress Controller.
+---
+
### -service-insight-listen-port ``
Sets the port where the Service Insight is exposed.
@@ -358,6 +444,8 @@ Format: `[1024 - 65535]` (default `9114`)
+---
+
### -service-insight-tls-secret ``
A Secret with a TLS certificate and key for TLS termination of the Service Insight endpoint.
@@ -369,6 +457,8 @@ Format: `/`
+---
+
### -spire-agent-address ``
Specifies the address of a running Spire agent. **For use with NGINX Service Mesh only**.
@@ -378,6 +468,8 @@ Specifies the address of a running Spire agent. **For use with NGINX Service Mes
+---
+
### -enable-internal-routes
Enable support for internal routes with NGINX Service Mesh. **For use with NGINX Service Mesh only**.
@@ -386,9 +478,10 @@ Requires [-spire-agent-address](#cmdoption-spire-agent-address).
- If the argument is set, but `spire-agent-address` is not provided, NGINX Ingress Controller will fail to start.
-
+---
+
### -enable-latency-metrics
Enable collection of latency metrics for upstreams.
@@ -396,6 +489,8 @@ Requires [-enable-prometheus-metrics](#cmdoption-enable-prometheus-metrics).
+---
+
### -enable-app-protect
Enables support for App Protect.
@@ -404,9 +499,10 @@ Requires [-nginx-plus](#cmdoption-nginx-plus).
- If the argument is set, but `nginx-plus` is set to false, NGINX Ingress Controller will fail to start.
-
+---
+
### -app-protect-log-level ``
Sets log level for App Protect. Allowed values: fatal, error, warn, info, debug, trace.
@@ -415,9 +511,10 @@ Requires [-nginx-plus](#cmdoption-nginx-plus) and [-enable-app-protect](#cmdopti
- If the argument is set, but `nginx-plus` and `enable-app-protect` are set to false, NGINX Ingress Controller will fail to start.
-
+---
+
### -enable-app-protect-dos
Enables support for App Protect DoS.
@@ -426,9 +523,10 @@ Requires [-nginx-plus](#cmdoption-nginx-plus).
- If the argument is set, but `nginx-plus` is set to false, NGINX Ingress Controller will fail to start.
-
+---
+
### -app-protect-dos-debug
Enable debugging for App Protect DoS.
@@ -437,9 +535,10 @@ Requires [-nginx-plus](#cmdoption-nginx-plus) and [-enable-app-protect-dos](#cmd
- If the argument is set, but `nginx-plus` and `enable-app-protect-dos` are set to false, NGINX Ingress Controller will fail to start.
-
+---
+
### -app-protect-dos-max-daemons
Max number of ADMD instances.
@@ -450,9 +549,10 @@ Requires [-nginx-plus](#cmdoption-nginx-plus) and [-enable-app-protect-dos](#cmd
- If the argument is set, but `nginx-plus` and `enable-app-protect-dos` are set to false, NGINX Ingress Controller will fail to start.
-
+---
+
### -app-protect-dos-max-workers
Max number of nginx processes to support.
@@ -463,9 +563,10 @@ Requires [-nginx-plus](#cmdoption-nginx-plus) and [-enable-app-protect-dos](#cmd
- If the argument is set, but `nginx-plus` and `enable-app-protect-dos` are set to false, NGINX Ingress Controller will fail to start.
-
+---
+
### -app-protect-dos-memory
RAM memory size to consume in MB
@@ -478,6 +579,8 @@ Requires [-nginx-plus](#cmdoption-nginx-plus) and [-enable-app-protect-dos](#cmd
+---
+
### -ready-status
Enables the readiness endpoint `/nginx-ready`. The endpoint returns a success code when NGINX has loaded all the config after the startup.
@@ -486,12 +589,15 @@ Default `true`.
+---
+
### -ready-status-port
The HTTP port for the readiness endpoint.
Format: `[1024 - 65535]` (default `8081`)
+---
### -disable-ipv6
@@ -501,6 +607,8 @@ Default `false`.
+---
+
### -default-http-listener-port
Sets the port for the HTTP `default_server` listener.
@@ -509,6 +617,8 @@ Default `80`.
+---
+
### -default-https-listener-port
Sets the port for the HTTPS `default_server` listener.
@@ -517,6 +627,8 @@ Default `443`.
+---
+
### -ssl-dynamic-reload
Used to activate or deactivate lazy loading for SSL Certificates.
@@ -525,6 +637,8 @@ The default value is `true`.
+---
+
### -weight-changes-dynamic-reload
Enables the ability to change the weight distribution of two-way split clients without reloading NGINX.
@@ -539,6 +653,8 @@ The default value is `false`.
+---
+
### -enable-telemetry-reporting
Enable gathering and reporting of software telemetry.
@@ -547,6 +663,8 @@ The default value is `true`.
+---
+
### -agent
Enable NGINX Agent which can used with `-enable-app-protect` to send events to Security Monitoring.
@@ -555,6 +673,8 @@ The default value is `false`.
+---
+
### -agent-instance-group
Specify the instance group name to use for the NGINX Ingress Controller deployment when using `-agent`.
diff --git a/docs/content/configuration/global-configuration/configmap-resource.md b/docs/content/configuration/global-configuration/configmap-resource.md
index bf306083c7..8eedab536e 100644
--- a/docs/content/configuration/global-configuration/configmap-resource.md
+++ b/docs/content/configuration/global-configuration/configmap-resource.md
@@ -2,16 +2,16 @@
docs: DOCS-586
doctypes:
- ''
-title: ConfigMap Resources
+title: ConfigMap resources
toc: true
-weight: 1600
+weight: 300
---
-The ConfigMap Resources allows you to customize or fine tune NGINX behavior. Examples include setting the number of worker processes or customizing the access log format.
+When using F5 NGINX Ingress Controller, you can customize or fine tune NGINX behavior using ConfigMap resources. Examples include setting the number of worker processes or customizing the access log format.
## Using ConfigMap
-1. The [Installation with Manifests]({{< relref "/installation/installing-nic/installation-with-manifests.md" >}}) documentation deploy an empty ConfigMap while the default installation manifests specify it in the command-line arguments of the Ingress Controller. However, if you customized the manifests, to use ConfigMap, make sure to specify the ConfigMap resource to use the [command-line arguments]({{< relref "/configuration/global-configuration/command-line-arguments" >}}) of NGINX Ingress Controller.
+1. The [Installation with Manifests]({{< relref "installation/installing-nic/installation-with-manifests.md" >}}) documentation deploy an empty ConfigMap while the default installation manifests specify it in the command-line arguments of the Ingress Controller. However, if you customized the manifests, to use ConfigMap, make sure to specify the ConfigMap resource to use the [command-line arguments]({{< relref "configuration/global-configuration/command-line-arguments" >}}) of NGINX Ingress Controller.
1. Create a ConfigMap file with the name *nginx-config.yaml* and set the values
that make sense for your setup:
@@ -32,164 +32,184 @@ that make sense for your setup:
1. Create a new (or update the existing) ConfigMap resource:
- ```
+ ```shell
kubectl apply -f nginx-config.yaml
```
The NGINX configuration will be updated.
-## ConfigMap and Ingress Annotations
+---
+
+## ConfigMap and Ingress annotations
-Annotations allow you to configure advanced NGINX features and customize or fine tune NGINX behavior.
+ConfigMap applies globally, meaning that it affects every Ingress resource. In contrast, annotations always apply to their Ingress resource. Annotations can override some ConfigMap keys: an example is that the `nginx.org/proxy-connect-timeout` annotations overrides the `proxy-connect-timeout` ConfigMap key.
-The ConfigMap applies globally, meaning that it affects every Ingress resource. In contrast, annotations always apply to their Ingress resource. Annotations allow overriding some ConfigMap keys. For example, the `nginx.org/proxy-connect-timeout` annotations overrides the `proxy-connect-timeout` ConfigMap key.
+For more information, view the [Advanced configuration with annotations]({{< relref "configuration/ingress-resources/advanced-configuration-with-annotations" >}}) topic.
-See the doc about [annotations](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations).
+---
-## ConfigMap and VirtualServer/VirtualServerRoute Resource
+## ConfigMap and VirtualServer/VirtualServerRoute resources
The ConfigMap affects every VirtualServer and VirtualServerRoute resources. However, the fields of those resources allow overriding some ConfigMap keys. For example, the `connect-timeout` field of the `upstream` overrides the `proxy-connect-timeout` ConfigMap key.
-See the doc about [VirtualServer and VirtualServerRoute resources](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources).
+For more information, view the [VirtualServer and VirtualServerRoute resources]({{< relref "configuration/virtualserver-and-virtualserverroute-resources" >}}) topic.
-## Summary of ConfigMap Keys
+---
+
+## ConfigMap keys
-### Ingress Controller (Not Related to NGINX Configuration)
+### Ingress Controller (Unrelated to NGINX Configuration)
-{{% table %}}
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``external-status-address`` | Sets the address to be reported in the status of Ingress resources. Requires the ``-report-status`` command-line argument. Overrides the ``-external-service`` argument. | N/A | [Report Ingress Status](/nginx-ingress-controller/configuration/global-configuration/reporting-resources-status). |
-{{% /table %}}
+|*external-status-address* | Sets the address to be reported in the status of Ingress resources. Requires the *-report-status* command-line argument. Overrides the *-external-service* argument. | N/A | [Reporting resource status]({{< relref "configuration/global-configuration/reporting-resources-status" >}}) |
+{{}}
-### General Customization
+---
-{{% table %}}
+### General customization
+
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``proxy-connect-timeout`` | Sets the value of the [proxy_connect_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout) and [grpc_connect_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_connect_timeout) directive. | ``60s`` | |
-|``proxy-read-timeout`` | Sets the value of the [proxy_read_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout) and [grpc_read_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_read_timeout) directive. | ``60s`` | |
-|``proxy-send-timeout`` | Sets the value of the [proxy_send_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout) and [grpc_send_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_send_timeout) directive. | ``60s`` | |
-|``client-max-body-size`` | Sets the value of the [client_max_body_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) directive. | ``1m`` | |
-|``proxy-buffering`` | Enables or disables [buffering of responses](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering) from the proxied server. | ``True`` | |
-|``proxy-buffers`` | Sets the value of the [proxy_buffers](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers) directive. | Depends on the platform. | |
-|``proxy-buffer-size`` | Sets the value of the [proxy_buffer_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size) and [grpc_buffer_size](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_buffer_size) directives. | Depends on the platform. | |
-|``proxy-max-temp-file-size`` | Sets the value of the [proxy_max_temp_file_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_max_temp_file_size) directive. | ``1024m`` | |
-|``set-real-ip-from`` | Sets the value of the [set_real_ip_from](https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from) directive. | N/A | |
-|``real-ip-header`` | Sets the value of the [real_ip_header](https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header) directive. | ``X-Real-IP`` | |
-|``real-ip-recursive`` | Enables or disables the [real_ip_recursive](https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive) directive. | ``False`` | |
-|``default-server-return`` | Configures the [return](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return) directive in the default server, which handles a client request if none of the hosts of Ingress or VirtualServer resources match. The default value configures NGINX to return a 404 error page. You can configure a fixed response or a redirect. For example, ``default-server-return: 302 https://nginx.org`` will redirect a client to ``https://nginx.org``. | ``404`` | |
-|``server-tokens`` | Enables or disables the [server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) directive. Additionally, with the NGINX Plus, you can specify a custom string value, including the empty string value, which disables the emission of the “Server” field. | ``True`` | |
-|``worker-processes`` | Sets the value of the [worker_processes](https://nginx.org/en/docs/ngx_core_module.html#worker_processes) directive. | ``auto`` | |
-|``worker-rlimit-nofile`` | Sets the value of the [worker_rlimit_nofile](https://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile) directive. | N/A | |
-|``worker-connections`` | Sets the value of the [worker_connections](https://nginx.org/en/docs/ngx_core_module.html#worker_connections) directive. | ``1024`` | |
-|``worker-cpu-affinity`` | Sets the value of the [worker_cpu_affinity](https://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity) directive. | N/A | |
-|``worker-shutdown-timeout`` | Sets the value of the [worker_shutdown_timeout](https://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout) directive. | N/A | |
-|``server-names-hash-bucket-size`` | Sets the value of the [server_names_hash_bucket_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_names_hash_bucket_size) directive. | ``256`` | |
-|``server-names-hash-max-size`` | Sets the value of the [server_names_hash_max_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_names_hash_max_size) directive. | ``1024`` | |
-|``map-hash-bucket-size`` | Sets the value of the [map_hash_bucket_size](http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_bucket_size) directive.| ``256`` | |
-|``map-hash-max-size`` | Sets the value of the [map_hash_max_size](http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_max_size) directive. | ``2048`` | |
-|``resolver-addresses`` | Sets the value of the [resolver](https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver) addresses. Note: If you use a DNS name (for example, ``kube-dns.kube-system.svc.cluster.local`` ) as a resolver address, NGINX Plus will resolve it using the system resolver during the start and on every configuration reload. If the name cannot be resolved or the DNS server doesn't respond, NGINX Plus will fail to start or reload. To avoid this, we recommend using IP addresses as resolver addresses instead of DNS names. Supported in NGINX Plus only. | N/A | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
-|``resolver-ipv6`` | Enables IPv6 resolution in the resolver. Supported in NGINX Plus only. | ``True`` | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
-|``resolver-valid`` | Sets the time NGINX caches the resolved DNS records. Supported in NGINX Plus only. | TTL value of a DNS record | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
-|``resolver-timeout`` | Sets the [resolver_timeout](https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver_timeout) for name resolution. Supported in NGINX Plus only. | ``30s`` | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
-|``keepalive-timeout`` | Sets the value of the [keepalive_timeout](https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout) directive. | ``75s`` | |
-|``keepalive-requests`` | Sets the value of the [keepalive_requests](https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests) directive. | ``1000`` | |
-|``variables-hash-bucket-size`` | Sets the value of the [variables_hash_bucket_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#variables_hash_bucket_size) directive. | ``256`` | |
-|``variables-hash-max-size`` | Sets the value of the [variables-hash-max-size](https://nginx.org/en/docs/http/ngx_http_core_module.html#variables_hash_max_size) directive. | ``1024`` | |
-{{% /table %}}
+|*proxy-connect-timeout* | Sets the value of the [proxy_connect_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout) and [grpc_connect_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_connect_timeout) directive. | *60s* | |
+|*proxy-read-timeout* | Sets the value of the [proxy_read_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout) and [grpc_read_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_read_timeout) directive. | *60s* | |
+|*proxy-send-timeout* | Sets the value of the [proxy_send_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout) and [grpc_send_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_send_timeout) directive. | *60s* | |
+|*client-max-body-size* | Sets the value of the [client_max_body_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) directive. | *1m* | |
+|*proxy-buffering* | Enables or disables [buffering of responses](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering) from the proxied server. | *True* | |
+|*proxy-buffers* | Sets the value of the [proxy_buffers](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers) directive. | Depends on the platform. | |
+|*proxy-buffer-size* | Sets the value of the [proxy_buffer_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size) and [grpc_buffer_size](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_buffer_size) directives. | Depends on the platform. | |
+|*proxy-max-temp-file-size* | Sets the value of the [proxy_max_temp_file_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_max_temp_file_size) directive. | *1024m* | |
+|*set-real-ip-from* | Sets the value of the [set_real_ip_from](https://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from) directive. | N/A | |
+|*real-ip-header* | Sets the value of the [real_ip_header](https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header) directive. | *X-Real-IP* | |
+|*real-ip-recursive* | Enables or disables the [real_ip_recursive](https://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive) directive. | *False* | |
+|*default-server-return* | Configures the [return](https://nginx.org/en/docs/http/ngx_http_rewrite_module.html#return) directive in the default server, which handles a client request if none of the hosts of Ingress or VirtualServer resources match. The default value configures NGINX to return a 404 error page. You can configure a fixed response or a redirect. For example, *default-server-return: 302 https://nginx.org* will redirect a client to *https://nginx.org*. | *404* | |
+|*server-tokens* | Enables or disables the [server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) directive. Additionally, with the NGINX Plus, you can specify a custom string value, including the empty string value, which disables the emission of the “Server” field. | *True* | |
+|*worker-processes* | Sets the value of the [worker_processes](https://nginx.org/en/docs/ngx_core_module.html#worker_processes) directive. | *auto* | |
+|*worker-rlimit-nofile* | Sets the value of the [worker_rlimit_nofile](https://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile) directive. | N/A | |
+|*worker-connections* | Sets the value of the [worker_connections](https://nginx.org/en/docs/ngx_core_module.html#worker_connections) directive. | *1024* | |
+|*worker-cpu-affinity* | Sets the value of the [worker_cpu_affinity](https://nginx.org/en/docs/ngx_core_module.html#worker_cpu_affinity) directive. | N/A | |
+|*worker-shutdown-timeout* | Sets the value of the [worker_shutdown_timeout](https://nginx.org/en/docs/ngx_core_module.html#worker_shutdown_timeout) directive. | N/A | |
+|*server-names-hash-bucket-size* | Sets the value of the [server_names_hash_bucket_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_names_hash_bucket_size) directive. | *256* | |
+|*server-names-hash-max-size* | Sets the value of the [server_names_hash_max_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_names_hash_max_size) directive. | *1024* | |
+|*map-hash-bucket-size* | Sets the value of the [map_hash_bucket_size](http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_bucket_size) directive.| *256* | |
+|*map-hash-max-size* | Sets the value of the [map_hash_max_size](http://nginx.org/en/docs/http/ngx_http_map_module.html#map_hash_max_size) directive. | *2048* | |
+|*resolver-addresses* | Sets the value of the [resolver](https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver) addresses. Note: If you use a DNS name (for example, *kube-dns.kube-system.svc.cluster.local* ) as a resolver address, NGINX Plus will resolve it using the system resolver during the start and on every configuration reload. If the name cannot be resolved or the DNS server doesn't respond, NGINX Plus will fail to start or reload. To avoid this, we recommend using IP addresses as resolver addresses instead of DNS names. Supported in NGINX Plus only. | N/A | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
+|*resolver-ipv6* | Enables IPv6 resolution in the resolver. Supported in NGINX Plus only. | *True* | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
+|*resolver-valid* | Sets the time NGINX caches the resolved DNS records. Supported in NGINX Plus only. | TTL value of a DNS record | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
+|*resolver-timeout* | Sets the [resolver_timeout](https://nginx.org/en/docs/http/ngx_http_core_module.html#resolver_timeout) for name resolution. Supported in NGINX Plus only. | *30s* | [Support for Type ExternalName Services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services). |
+|*keepalive-timeout* | Sets the value of the [keepalive_timeout](https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout) directive. | *75s* | |
+|*keepalive-requests* | Sets the value of the [keepalive_requests](https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_requests) directive. | *1000* | |
+|*variables-hash-bucket-size* | Sets the value of the [variables_hash_bucket_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#variables_hash_bucket_size) directive. | *256* | |
+|*variables-hash-max-size* | Sets the value of the [variables-hash-max-size](https://nginx.org/en/docs/http/ngx_http_core_module.html#variables_hash_max_size) directive. | *1024* | |
+{{}}
+
+---
### Logging
-{{% table %}}
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``error-log-level`` | Sets the global [error log level](https://nginx.org/en/docs/ngx_core_module.html#error_log) for NGINX. | ``notice`` | |
-|``access-log-off`` | Disables the [access log](https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log). | ``False`` | |
-|``default-server-access-log-off`` | Disables the [access log](https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log) for the default server. If access log is disabled globally (``access-log-off: "True"``), then the default server access log is always disabled. | ``False`` | |
-|``log-format`` | Sets the custom [log format](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format) for HTTP and HTTPS traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by ``\n``). In that case, the Ingress Controller will replace every ``\n`` character with a space character. All ``'`` characters must be escaped. | See the [template file](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/internal/configs/version1/nginx.tmpl) for the access log. | [Custom Log Format](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/shared-examples/custom-log-format). |
-|``log-format-escaping`` | Sets the characters escaping for the variables of the log format. Supported values: ``json`` (JSON escaping), ``default`` (the default escaping) ``none`` (disables escaping). | ``default`` | |
-|``stream-log-format`` | Sets the custom [log format](https://nginx.org/en/docs/stream/ngx_stream_log_module.html#log_format) for TCP, UDP, and TLS Passthrough traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by ``\n``). In that case, the Ingress Controller will replace every ``\n`` character with a space character. All ``'`` characters must be escaped. | See the [template file](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/internal/configs/version1/nginx.tmpl). | |
-|``stream-log-format-escaping`` | Sets the characters escaping for the variables of the stream log format. Supported values: ``json`` (JSON escaping), ``default`` (the default escaping) ``none`` (disables escaping). | ``default`` | |
-{{% /table %}}
-
-### Request URI/Header Manipulation
-
-{{% table %}}
+|*error-log-level* | Sets the global [error log level](https://nginx.org/en/docs/ngx_core_module.html#error_log) for NGINX. | *notice* | |
+|*access-log-off* | Disables the [access log](https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log). | *False* | |
+|*default-server-access-log-off* | Disables the [access log](https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log) for the default server. If access log is disabled globally (*access-log-off: "True"*), then the default server access log is always disabled. | *False* | |
+|*log-format* | Sets the custom [log format](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format) for HTTP and HTTPS traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by *\n*). In that case, the Ingress Controller will replace every *\n* character with a space character. All *'* characters must be escaped. | See the [template file](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/internal/configs/version1/nginx.tmpl) for the access log. | [Custom Log Format](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/shared-examples/custom-log-format). |
+|*log-format-escaping* | Sets the characters escaping for the variables of the log format. Supported values: *json* (JSON escaping), *default* (the default escaping) *none* (disables escaping). | *default* | |
+|*stream-log-format* | Sets the custom [log format](https://nginx.org/en/docs/stream/ngx_stream_log_module.html#log_format) for TCP, UDP, and TLS Passthrough traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by *\n*). In that case, the Ingress Controller will replace every *\n* character with a space character. All *'* characters must be escaped. | See the [template file](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/internal/configs/version1/nginx.tmpl). | |
+|*stream-log-format-escaping* | Sets the characters escaping for the variables of the stream log format. Supported values: *json* (JSON escaping), *default* (the default escaping) *none* (disables escaping). | *default* | |
+{{}}
+
+---
+
+### Request URI/Header manipulation
+
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``proxy-hide-headers`` | Sets the value of one or more [proxy_hide_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header) directives. Example: ``"nginx.org/proxy-hide-headers": "header-a,header-b"`` | N/A | |
-|``proxy-pass-headers`` | Sets the value of one or more [proxy_pass_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_header) directives. Example: ``"nginx.org/proxy-pass-headers": "header-a,header-b"`` | N/A | |
-{{% /table %}}
+|*proxy-hide-headers* | Sets the value of one or more [proxy_hide_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header) directives. Example: *"nginx.org/proxy-hide-headers": "header-a,header-b"* | N/A | |
+|*proxy-pass-headers* | Sets the value of one or more [proxy_pass_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_header) directives. Example: *"nginx.org/proxy-pass-headers": "header-a,header-b"* | N/A | |
+{{}}
+
+---
### Auth and SSL/TLS
-{{% table %}}
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``redirect-to-https`` | Sets the 301 redirect rule based on the value of the ``http_x_forwarded_proto`` header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress Controller — see [115](https://github.com/nginxinc/kubernetes-ingress/issues/115) | ``False`` | |
-|``ssl-redirect`` | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | ``True`` | |
-|``hsts`` | Enables [HTTP Strict Transport Security (HSTS)](https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/) : the HSTS header is added to the responses from backends. The ``preload`` directive is included in the header. | ``False`` | |
-|``hsts-max-age`` | Sets the value of the ``max-age`` directive of the HSTS header. | ``2592000`` (1 month) | |
-|``hsts-include-subdomains`` | Adds the ``includeSubDomains`` directive to the HSTS header. | ``False`` | |
-|``hsts-behind-proxy`` | Enables HSTS based on the value of the ``http_x_forwarded_proto`` request header. Should only be used when TLS termination is configured in a load balancer (proxy) in front of the Ingress Controller. Note: to control redirection from HTTP to HTTPS configure the ``nginx.org/redirect-to-https`` annotation. | ``False`` | |
-|``ssl-protocols`` | Sets the value of the [ssl_protocols](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols) directive. | ``TLSv1 TLSv1.1 TLSv1.2`` | |
-|``ssl-prefer-server-ciphers`` | Enables or disables the [ssl_prefer_server_ciphers](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers) directive. | ``False`` | |
-|``ssl-ciphers`` | Sets the value of the [ssl_ciphers](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers) directive. | ``HIGH:!aNULL:!MD5`` | |
-|``ssl-dhparam-file`` | Sets the content of the dhparam file. The controller will create the file and set the value of the [ssl_dhparam](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam) directive with the path of the file. | N/A | |
-{{% /table %}}
+|*redirect-to-https* | Sets the 301 redirect rule based on the value of the *http_x_forwarded_proto* header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress Controller — see [115](https://github.com/nginxinc/kubernetes-ingress/issues/115) | *False* | |
+|*ssl-redirect* | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | *True* | |
+|*hsts* | Enables [HTTP Strict Transport Security (HSTS)](https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/) : the HSTS header is added to the responses from backends. The *preload* directive is included in the header. | *False* | |
+|*hsts-max-age* | Sets the value of the *max-age* directive of the HSTS header. | *2592000* (1 month) | |
+|*hsts-include-subdomains* | Adds the *includeSubDomains* directive to the HSTS header. | *False* | |
+|*hsts-behind-proxy* | Enables HSTS based on the value of the *http_x_forwarded_proto* request header. Should only be used when TLS termination is configured in a load balancer (proxy) in front of the Ingress Controller. Note: to control redirection from HTTP to HTTPS configure the *nginx.org/redirect-to-https* annotation. | *False* | |
+|*ssl-protocols* | Sets the value of the [ssl_protocols](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_protocols) directive. | *TLSv1 TLSv1.1 TLSv1.2* | |
+|*ssl-prefer-server-ciphers* | Enables or disables the [ssl_prefer_server_ciphers](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_prefer_server_ciphers) directive. | *False* | |
+|*ssl-ciphers* | Sets the value of the [ssl_ciphers](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers) directive. | *HIGH:!aNULL:!MD5* | |
+|*ssl-dhparam-file* | Sets the content of the dhparam file. The controller will create the file and set the value of the [ssl_dhparam](https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam) directive with the path of the file. | N/A | |
+{{}}
+
+---
### Listeners
-{{% table %}}
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``http2`` | Enables HTTP/2 in servers with SSL enabled. | ``False`` | |
-|``proxy-protocol`` | Enables PROXY Protocol for incoming connections. | ``False`` | [Proxy Protocol](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/shared-examples/proxy-protocol). |
-{{% /table %}}
+|*http2* | Enables HTTP/2 in servers with SSL enabled. | *False* | |
+|*proxy-protocol* | Enables PROXY Protocol for incoming connections. | *False* | [Proxy Protocol](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/shared-examples/proxy-protocol). |
+{{}}
+
+---
-### Backend Services (Upstreams)
+### Backend services (Upstreams)
-{{% table %}}
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``lb-method`` | Sets the [load balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify ``"round_robin"``. | ``"random two least_conn"`` | |
-|``max-fails`` | Sets the value of the [max_fails](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails) parameter of the ``server`` directive. | ``1`` | |
-|``upstream-zone-size`` | Sets the size of the shared memory [zone](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone) for upstreams. For NGINX, the special value 0 disables the shared memory zones. For NGINX Plus, shared memory zones are required and cannot be disabled. The special value 0 will be ignored. | ``256k`` for NGINX, ``512k`` for NGINX Plus | |
-|``fail-timeout`` | Sets the value of the [fail_timeout](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#fail_timeout) parameter of the ``server`` directive. | ``10s`` | |
-|``keepalive`` | Sets the value of the [keepalive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive. Note that ``proxy_set_header Connection "";`` is added to the generated configuration when the value > 0. | ``0`` | |
-{{% /table %}}
+|*lb-method* | Sets the [load balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify *"round_robin"*. | *"random two least_conn"* | |
+|*max-fails* | Sets the value of the [max_fails](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails) parameter of the *server* directive. | *1* | |
+|*upstream-zone-size* | Sets the size of the shared memory [zone](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone) for upstreams. For NGINX, the special value 0 disables the shared memory zones. For NGINX Plus, shared memory zones are required and cannot be disabled. The special value 0 will be ignored. | *256k* for NGINX, *512k* for NGINX Plus | |
+|*fail-timeout* | Sets the value of the [fail_timeout](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#fail_timeout) parameter of the *server* directive. | *10s* | |
+|*keepalive* | Sets the value of the [keepalive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive. Note that *proxy_set_header Connection "";* is added to the generated configuration when the value > 0. | *0* | |
+{{}}
-### Snippets and Custom Templates
+---
+
+### Snippets and custom templates
-{{% table %}}
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``main-snippets`` | Sets a custom snippet in main context. | N/A | |
-|``http-snippets`` | Sets a custom snippet in http context. | N/A | |
-|``location-snippets`` | Sets a custom snippet in location context. | N/A | |
-|``server-snippets`` | Sets a custom snippet in server context. | N/A | |
-|``stream-snippets`` | Sets a custom snippet in stream context. | N/A | [Support for TCP/UDP Load Balancing](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/tcp-udp). |
-|``main-template`` | Sets the main NGINX configuration template. | By default the template is read from the file in the container. | [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates). |
-|``ingress-template`` | Sets the NGINX configuration template for an Ingress resource. | By default the template is read from the file on the container. | [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates). |
-|``virtualserver-template`` | Sets the NGINX configuration template for an VirtualServer resource. | By default the template is read from the file on the container. | [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates). |
-{{% /table %}}
-
-### Modules {#modules}
-
-{{% table %}}
+|*main-snippets* | Sets a custom snippet in main context. | N/A | |
+|*http-snippets* | Sets a custom snippet in http context. | N/A | |
+|*location-snippets* | Sets a custom snippet in location context. | N/A | |
+|*server-snippets* | Sets a custom snippet in server context. | N/A | |
+|*stream-snippets* | Sets a custom snippet in stream context. | N/A | [Support for TCP/UDP Load Balancing](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/tcp-udp). |
+|*main-template* | Sets the main NGINX configuration template. | By default the template is read from the file in the container. | [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates). |
+|*ingress-template* | Sets the NGINX configuration template for an Ingress resource. | By default the template is read from the file on the container. | [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates). |
+|*virtualserver-template* | Sets the NGINX configuration template for an VirtualServer resource. | By default the template is read from the file on the container. | [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates). |
+{{}}
+
+---
+
+### Modules
+
+{{}}
|ConfigMap Key | Description | Default | Example |
| ---| ---| ---| --- |
-|``opentracing`` | Enables [OpenTracing](https://opentracing.io) globally (for all Ingress, VirtualServer and VirtualServerRoute resources). Note: requires the Ingress Controller image with OpenTracing module and a tracer. See the [docs](/nginx-ingress-controller/third-party-modules/opentracing) for more information. | ``False`` | |
-|``opentracing-tracer`` | Sets the path to the vendor tracer binary plugin. | N/A | |
-|``opentracing-tracer-config`` | Sets the tracer configuration in JSON format. | N/A | |
-|``app-protect-compressed-requests-action`` | Sets the ``app_protect_compressed_requests_action`` [global directive](/nginx-app-protect/configuration/#global-directives). | ``drop`` | |
-|``app-protect-cookie-seed`` | Sets the ``app_protect_cookie_seed`` [global directive](/nginx-app-protect/configuration/#global-directives). | Random automatically generated string | |
-|``app-protect-failure-mode-action`` | Sets the ``app_protect_failure_mode_action`` [global directive](/nginx-app-protect/configuration/#global-directives). | ``pass`` | |
-|``app-protect-cpu-thresholds`` | Sets the ``app_protect_cpu_thresholds`` [global directive](/nginx-app-protect/configuration/#global-directives). | ``high=100 low=100`` | |
-|``app-protect-physical-memory-util-thresholds`` | Sets the ``app_protect_physical_memory_util_thresholds`` [global directive](/nginx-app-protect/configuration/#global-directives). | ``high=100 low=100`` | |
+|*opentracing* | Enables [OpenTracing](https://opentracing.io) globally (for all Ingress, VirtualServer and VirtualServerRoute resources). Note: requires the Ingress Controller image with OpenTracing module and a tracer. See the [docs](/nginx-ingress-controller/third-party-modules/opentracing) for more information. | *False* | |
+|*opentracing-tracer* | Sets the path to the vendor tracer binary plugin. | N/A | |
+|*opentracing-tracer-config* | Sets the tracer configuration in JSON format. | N/A | |
+|*app-protect-compressed-requests-action* | Sets the *app_protect_compressed_requests_action* [global directive](/nginx-app-protect/configuration/#global-directives). | *drop* | |
+|*app-protect-cookie-seed* | Sets the *app_protect_cookie_seed* [global directive](/nginx-app-protect/configuration/#global-directives). | Random automatically generated string | |
+|*app-protect-failure-mode-action* | Sets the *app_protect_failure_mode_action* [global directive](/nginx-app-protect/configuration/#global-directives). | *pass* | |
+|*app-protect-cpu-thresholds* | Sets the *app_protect_cpu_thresholds* [global directive](/nginx-app-protect/configuration/#global-directives). | *high=100 low=100* | |
+|*app-protect-physical-memory-util-thresholds* | Sets the *app_protect_physical_memory_util_thresholds* [global directive](/nginx-app-protect/configuration/#global-directives). | *high=100 low=100* | |
|`app-protect-reconnect-period-seconds` | Sets the `app_protect_reconnect_period_seconds` [global directive](/nginx-app-protect/configuration/#global-directives). | `5` | |
-|``app-protect-dos-log-format`` | Sets the custom [log format](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format) for Dos Access log traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by ``\n``). In that case, the Ingress Controller will replace every ``\n`` character with a space character. All ``'`` characters must be escaped. | `, vs_name_al=$app_protect_dos_vs_name, ip=$remote_addr, tls_fp=$app_protect_dos_tls_fp, outcome=$app_protect_dos_outcome, reason=$app_protect_dos_outcome_reason, policy_name=$app_protect_dos_policy_name, dos_version=$app_protect_dos_version, ip_tls=$remote_addr:$app_protect_dos_tls_fp,` | |
-|``app-protect-dos-log-format-escaping`` | Sets the characters escaping for the variables of the stream log format. Supported values: ``json`` (JSON escaping), ``default`` (the default escaping) ``none`` (disables escaping). | ``default`` | |
-|``app-protect-dos-arb-fqdn`` | Sets the ``app-protect-dos-arb-fqdn`` [directive](/nginx-app-protect-dos/directives-and-policy/learn-about-directives-and-policy/#arbitrator-fqdn-directive-app_protect_dos_arb_fqdn). | ``svc-appprotect-dos-arb`` | |
-{{% /table %}}
+|*app-protect-dos-log-format* | Sets the custom [log format](https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format) for Dos Access log traffic. For convenience, it is possible to define the log format across multiple lines (each line separated by *\n*). In that case, the Ingress Controller will replace every *\n* character with a space character. All *'* characters must be escaped. | `, vs_name_al=$app_protect_dos_vs_name, ip=$remote_addr, tls_fp=$app_protect_dos_tls_fp, outcome=$app_protect_dos_outcome, reason=$app_protect_dos_outcome_reason, policy_name=$app_protect_dos_policy_name, dos_version=$app_protect_dos_version, ip_tls=$remote_addr:$app_protect_dos_tls_fp,` | |
+|*app-protect-dos-log-format-escaping* | Sets the characters escaping for the variables of the stream log format. Supported values: *json* (JSON escaping), *default* (the default escaping) *none* (disables escaping). | *default* | |
+|*app-protect-dos-arb-fqdn* | Sets the *app-protect-dos-arb-fqdn* [directive](/nginx-app-protect-dos/directives-and-policy/learn-about-directives-and-policy/#arbitrator-fqdn-directive-app_protect_dos_arb_fqdn). | *svc-appprotect-dos-arb* | |
+{{}}
diff --git a/docs/content/configuration/global-configuration/custom-templates.md b/docs/content/configuration/global-configuration/custom-templates.md
index 0503b25ea1..60c391c578 100644
--- a/docs/content/configuration/global-configuration/custom-templates.md
+++ b/docs/content/configuration/global-configuration/custom-templates.md
@@ -2,10 +2,10 @@
docs: DOCS-587
doctypes:
- ''
-title: Custom Templates
+title: Custom templates
toc: true
-weight: 1800
+weight: 500
---
-The Ingress Controller uses templates to generate NGINX configuration for Ingress resources, VirtualServer resources and the main NGINX configuration file. You can customize the templates and apply them via the ConfigMap. See the [corresponding example](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/shared-examples/custom-templates).
+F5 NGINX Ingress Controller uses templates to generate NGINX configuration for Ingress resources, VirtualServer resources and the main NGINX configuration file. You can customize the templates and apply them via the ConfigMap. See the [corresponding example](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/shared-examples/custom-templates).
diff --git a/docs/content/configuration/global-configuration/globalconfiguration-resource.md b/docs/content/configuration/global-configuration/globalconfiguration-resource.md
index 33830af896..b91c7ee1c4 100644
--- a/docs/content/configuration/global-configuration/globalconfiguration-resource.md
+++ b/docs/content/configuration/global-configuration/globalconfiguration-resource.md
@@ -2,21 +2,26 @@
docs: DOCS-588
doctypes:
- ''
-title: GlobalConfiguration Resource
+title: GlobalConfiguration resource
toc: true
-weight: 2000
+weight: 200
---
-The GlobalConfiguration resource allows you to define the global configuration parameters of NGINX Ingress Controller. The resource is implemented as a [Custom Resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
+This page explains how to use the GlobalConfiguration resource to define the global configuration parameters of F5 NGINX Ingress Controller.
-The resource supports configuring listeners for TCP and UDP load balancing. Listeners are required by [TransportServer resources]({{< relref "/configuration/transportserver-resource.md" >}}) and
-can be used to [configure custom listeners for VirtualServers]({{< relref "tutorials/virtual-server-with-custom-listener-ports" >}}).
+The resource supports configuring listeners for TCP and UDP load balancing, and is implemented as a [Custom resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
+
+Listeners are required by [TransportServer resources]({{< relref "/configuration/transportserver-resource.md" >}}) and can be used to [configure custom listeners for VirtualServers]({{< relref "tutorials/virtual-server-with-custom-listener-ports.md" >}}).
+
+---
## Prerequisites
When [installing NGINX Ingress Controller using Manifests]({{< relref "/installation/installing-nic/installation-with-manifests.md" >}}), you need to reference a GlobalConfiguration resource in the [`-global-configuration`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-global-configuration) command-line argument. NGINX Ingress Controller only needs one GlobalConfiguration resource.
-## GlobalConfiguration Specification
+---
+
+## GlobalConfiguration specification
The GlobalConfiguration resource defines the global configuration parameters of the Ingress Controller. Below is an example:
@@ -43,11 +48,11 @@ spec:
ssl: true
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
-|``listeners`` | A list of listeners. | [[]listener](#listener) | No |
-{{% /table %}}
+| *listeners* | A list of listeners. | [listener](#listener) | No |
+{{}}
### Listener
@@ -62,14 +67,16 @@ The `listeners:` key defines a listener (a combination of a protocol and a port)
protocol: HTTP
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
-|``name`` | The name of the listener. Must be a valid DNS label as defined in RFC 1035. For example, ``hello`` and ``listener-123`` are valid. The name must be unique among all listeners. The name ``tls-passthrough`` is reserved for the built-in TLS Passthrough listener and cannot be used. | ``string`` | Yes |
-|``port`` | The port of the listener. The port must fall into the range ``1..65535`` with the following exceptions: ``80``, ``443``, the [status port](/nginx-ingress-controller/logging-and-monitoring/status-page), the [Prometheus metrics port](/nginx-ingress-controller/logging-and-monitoring/prometheus). Among all listeners, only a single combination of a port-protocol is allowed. | ``int`` | Yes |
-|``protocol`` | The protocol of the listener. Supported values: ``TCP``, ``UDP`` and ``HTTP``. | ``string`` | Yes |
-|``ssl`` | Configures the listener with SSL. This is currently only supported for ``HTTP`` listeners. Default value is ``false`` | ``bool`` | No |
-{{% /table %}}
+| *name* | The name of the listener. Must be a valid DNS label as defined in RFC 1035. For example, ``hello`` and ``listener-123`` are valid. The name must be unique among all listeners. The name ``tls-passthrough`` is reserved for the built-in TLS Passthrough listener and cannot be used. | *string* | Yes |
+| *port* | The port of the listener. The port must fall into the range ``1..65535`` with the following exceptions: ``80``, ``443``, the [status port](/nginx-ingress-controller/logging-and-monitoring/status-page), the [Prometheus metrics port](/nginx-ingress-controller/logging-and-monitoring/prometheus). Among all listeners, only a single combination of a port-protocol is allowed. | *int* | Yes |
+| *protocol* | The protocol of the listener. Supported values: ``TCP``, ``UDP`` and ``HTTP``. | *string* | Yes |
+| *ssl* | Configures the listener with SSL. This is currently only supported for ``HTTP`` listeners. Default value is ``false`` | *bool* | No |
+{{}}
+
+---
## Using GlobalConfiguration
@@ -79,6 +86,8 @@ For example, the following command creates a GlobalConfiguration resource define
```shell
kubectl apply -f global-configuration.yaml
+```
+```shell
globalconfiguration.k8s.nginx.org/nginx-configuration created
```
@@ -86,20 +95,25 @@ Assuming the namespace of the resource is `nginx-ingress`, you can get the resou
```shell
kubectl get globalconfiguration nginx-configuration -n nginx-ingress
+```
+```shell
NAME AGE
nginx-configuration 13s
```
-In the kubectl get and similar commands, you can also use the short name `gc` instead of `globalconfiguration`.
+With `kubectl get` and similar commands, you can use the short name `gc` instead of `globalconfiguration`.
+
+---
### Validation
Two types of validation are available for the GlobalConfiguration resource:
-- *Structural validation* by the `kubectl` and Kubernetes API server.
-- *Comprehensive validation* by the Ingress Controller.
+- *Structural validation* by `kubectl` and Kubernetes API server.
+- *Comprehensive validation* by NGINX Ingress Controller.
+
-#### Structural Validation
+#### Structural validation
The custom resource definition for the GlobalConfiguration includes structural OpenAPI schema which describes the type of every field of the resource.
@@ -107,43 +121,50 @@ If you try to create (or update) a resource that violates the structural schema
- Example of `kubectl` validation:
+ ```shell
+ kubectl apply -f global-configuration.yaml
```
- $ kubectl apply -f global-configuration.yaml
+ ```text
error: error validating "global-configuration.yaml": error validating data: ValidationError(GlobalConfiguration.spec.listeners[0].port): invalid type for org.nginx.k8s.v1.GlobalConfiguration.spec.listeners.port: got "string", expected "integer"; if you choose to ignore these errors, turn validation off with --validate=false
```
- Example of Kubernetes API server validation:
+ ```shell
+ kubectl apply -f global-configuration.yaml --validate=false
```
- $ kubectl apply -f global-configuration.yaml --validate=false
- The GlobalConfiguration "nginx-configuration" is invalid: []: Invalid value: map[string]interface {}{ ... }: validation failure list:
- spec.listeners.port in body must be of type integer: "string"
+ ```text
+ The GlobalConfiguration "nginx-configuration" is invalid: []: Invalid value: map[string]interface {}{ ... }: validation failure list:
+ spec.listeners.port in body must be of type integer: "string"
```
-If a resource is not rejected (it doesn't violate the structural schema), the Ingress Controller will validate it further.
+If a resource is not rejected (it doesn't violate the structural schema), NGINX Ingress Controller will validate it further.
-#### Comprehensive Validation
+#### Comprehensive validation
-The Ingress Controller validates the fields of a GlobalConfiguration resource. If a GlobalConfiguration resource is partially invalid, the Ingress Controller use the valid listeners and emit events about invalid listeners.
+NGINX Ingress Controller validates the fields of a GlobalConfiguration resource. If a GlobalConfiguration resource is partially invalid, NGINX Ingress Controller use the valid listeners and emit events about invalid listeners.
You can check if the Ingress Controller successfully applied the configuration for a GlobalConfiguration. For our `nginx-configuration` GlobalConfiguration, we can run:
```shell
kubectl describe gc nginx-configuration -n nginx-ingress
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Updated 11s nginx-ingress-controller GlobalConfiguration nginx-ingress/nginx-configuration was updated
```
-Note how the events section includes a Normal event with the Updated reason that informs us that the configuration was successfully applied.
+The events section includes a Normal event with the Updated reason that informs us that the configuration was successfully applied.
If you create a GlobalConfiguration `nginx-configuration` with two or more listeners that have the same protocol UDP and port 53, you will get:
```shell
kubectl describe gc nginx-configuration -n nginx-ingress
-. . .
+```
+```text
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
@@ -151,4 +172,4 @@ Events:
Warning AddedOrUpdatedWithError 6s nginx-ingress-controller GlobalConfiguration nginx-ingress/nginx-configuration is invalid and was rejected: spec.listeners: Duplicate value: "Duplicated port/protocol combination 53/UDP"
```
-Note how the events section includes a Warning event with the AddedOrUpdatedWithError reason.
+The events section includes a Warning event with the AddedOrUpdatedWithError reason.
diff --git a/docs/content/configuration/global-configuration/reporting-resources-status.md b/docs/content/configuration/global-configuration/reporting-resources-status.md
index 4c75281d60..8e36733ebf 100644
--- a/docs/content/configuration/global-configuration/reporting-resources-status.md
+++ b/docs/content/configuration/global-configuration/reporting-resources-status.md
@@ -2,40 +2,48 @@
docs: DOCS-589
doctypes:
- ''
-title: Reporting Resources Status
+title: Reporting resource status
toc: true
-weight: 1900
+weight: 600
---
-## Ingress Resources
+This page describes how to view the status of resources managed by F5 NGINX Ingress Controller.
+
+## Ingress resources
+
+An Ingress resource status includes the address (an IP address or a DNS name), through which the hosts of that Ingress resource are publicly accessible.
-An Ingress resource can have a status that includes the address (an IP address or a DNS name), through which the hosts of that Ingress resource are publicly accessible.
You can see the address in the output of the `kubectl get ingress` command, in the ADDRESS column, as shown below:
```shell
-$ kubectl get ingresses
+kubectl get ingresses
+```
+```text
NAME HOSTS ADDRESS PORTS AGE
cafe-ingress cafe.example.com 12.13.23.123 80, 443 2m
```
-The Ingress Controller must be configured to report an Ingress status:
+NGINX Ingress Controller must be configured to report an Ingress status:
1. Use the command-line flag `-report-ingress-status`.
-2. Define a source for an external address. This can be either of:
+1. Define a source for an external address. This can be either of:
1. A user defined address, specified in the `external-status-address` ConfigMap key.
- 2. A Service of the type LoadBalancer configured with an external IP or address and specified by the `-external-service` command-line flag.
+ 1. A Service of the type LoadBalancer configured with an external IP or address and specified by the `-external-service` command-line flag.
-See the docs about [ConfigMap keys](/nginx-ingress-controller/configuration/global-configuration/configmap-resource) and [Command-line arguments](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments).
+View the [ConfigMap keys](/nginx-ingress-controller/configuration/global-configuration/configmap-resource) and [Command-line arguments](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments) topics for more information.
-Notes: NGINX Ingress Controller does not clear the status of Ingress resources when it is being shut down.
+{{< note >}} NGINX Ingress Controller does not clear the status of Ingress resources when it is being shut down. {{< /note >}}
-## VirtualServer and VirtualServerRoute Resources
+## VirtualServer and VirtualServerRoute resources
A VirtualServer or VirtualServerRoute resource includes the status field with information about the state of the resource and the IP address, through which the hosts of that resource are publicly accessible.
+
You can see the status in the output of the `kubectl get virtualservers` or `kubectl get virtualserverroutes` commands as shown below:
```shell
kubectl get virtualservers
+```
+```text
NAME STATE HOST IP PORTS AGE
cafe Valid cafe.example.com 12.13.23.123 [80,443] 34s
```
@@ -44,17 +52,21 @@ To see an external hostname address associated with a VirtualServer resource, us
```shell
kubectl get virtualservers -o wide
+```
+```text
NAME STATE HOST IP EXTERNALHOSTNAME PORTS AGE
cafe Valid cafe.example.com ae430f41a1a0042908655abcdefghijkl-12345678.eu-west-2.elb.amazonaws.com [80,443] 106s
```
-> Note: If there are multiple addresses, only the first one is shown.
+{{< note >}} If there are multiple addresses, only the first one is shown. {{< /note >}}
In order to see additional addresses or extra information about the `Status` of the resource, use the following command:
```shell
kubectl describe virtualserver
-. . .
+```
+```text
+...
Status:
External Endpoints:
Ip: 12.13.23.123
@@ -64,54 +76,57 @@ Status:
State: Valid
```
-### Status Specification
+### Status specification
The following fields are reported in both VirtualServer and VirtualServerRoute status:
-{{% table %}}
+{{}}
|Field | Description | Type |
| ---| ---| --- |
-|``State`` | Current state of the resource. Can be ``Valid``, ``Warning`` an ``Invalid``. For more information, refer to the ``message`` field. | ``string`` |
-|``Reason`` | The reason of the last update. | ``string`` |
-|``Message`` | Additional information about the state. | ``string`` |
-|``ExternalEndpoints`` | A list of external endpoints for which the hosts of the resource are publicly accessible. | [[]externalEndpoint](#externalendpoint) |
-{{% /table %}}
+|*State* | Current state of the resource. Can be ``Valid``, ``Warning`` an ``Invalid``. For more information, refer to the ``message`` field. | *string* |
+|*Reason* | The reason of the last update. | *string* |
+|*Message* | Additional information about the state. | *string* |
+|*ExternalEndpoints* | A list of external endpoints for which the hosts of the resource are publicly accessible. | *[externalEndpoint](#externalendpoint)* |
+{{}}
-The following field is reported in the VirtualServerRoute status only:
+The *ReferencedBy* field is reported for the VirtualServerRoute status only:
-{{% table %}}
+{{}}
|Field | Description | Type |
| ---| ---| --- |
-|``ReferencedBy`` | The VirtualServer that references this VirtualServerRoute. Format is ``namespace/name`` | ``string`` |
-{{% /table %}}
+| *ReferencedBy* | The VirtualServer that references this VirtualServerRoute. Format as ``namespace/name`` | *string* |
+{{}}
-### ExternalEndpoint
+### externalEndpoint
-{{% table %}}
+{{}}
|Field | Description | Type |
| ---| ---| --- |
|``IP`` | The external IP address. | ``string`` |
|``Hostname`` | The external LoadBalancer Hostname address. | ``string`` |
|``Ports`` | A list of external ports. | ``string`` |
-{{% /table %}}
+{{}}
-The Ingress Controller must be configured to report a VirtualServer or VirtualServerRoute status:
+NGINX Ingress Controller must be configured to report a VirtualServer or VirtualServerRoute status:
-1. If you want the Ingress Controller to report the `externalEndpoints`, define a source for an external address (Note: the rest of the fields will be reported without the external address configured). This can be either of:
+1. If you want NGINX Ingress Controller to report the `externalEndpoints`, define a source for an external address (The rest of the fields will be reported without the external address configured). This can be:
1. A user defined address, specified in the `external-status-address` ConfigMap key.
- 2. A Service of the type LoadBalancer configured with an external IP or address and specified by the `-external-service` command-line flag.
+ 1. A Service of the type LoadBalancer configured with an external IP or address and specified by the `-external-service` command-line flag.
-See the docs about [ConfigMap keys](/nginx-ingress-controller/configuration/global-configuration/configmap-resource) and [Command-line arguments](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments).
+View the [ConfigMap keys](/nginx-ingress-controller/configuration/global-configuration/configmap-resource) and [Command-line arguments](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments) topics for more information.
-Notes: The Ingress Controller does not clear the status of VirtualServer and VirtualServerRoute resources when it is being shut down.
+{{< note >}} NGINX Ingress Controller does not clear the status of VirtualServer and VirtualServerRoute resources when it is being shut down. {{< /note >}}
-## Policy Resources
+## Policy resources
A Policy resource includes the status field with information about the state of the resource.
+
You can see the status in the output of the `kubectl get policy` command as shown below:
```shell
kubectl get policy
+```
+```text
NAME STATE AGE
webapp-policy Valid 30s
```
@@ -120,55 +135,61 @@ In order to see additional addresses or extra information about the `Status` of
```shell
kubectl describe policy
-. . .
+```
+```text
+...
Status:
Message: Configuration for default/webapp-policy was added or updated
Reason: AddedOrUpdated
State: Valid
```
-### Status Specification
+### Status specification
The following fields are reported in Policy status:
-{{% table %}}
+{{}}
|Field | Description | Type |
| ---| ---| --- |
|``State`` | Current state of the resource. Can be ``Valid`` or ``Invalid``. For more information, refer to the ``message`` field. | ``string`` |
|``Reason`` | The reason of the last update. | ``string`` |
|``Message`` | Additional information about the state. | ``string`` |
-{{% /table %}}
+{{}}
-## TransportServer Resources
+## TransportServer resources
A TransportServer resource includes the status field with information about the state of the resource.
+
You can see the status in the output of the `kubectl get transportserver` command as shown below:
```shell
kubectl get transportserver
+```
+```text
NAME STATE REASON AGE
dns-tcp Valid AddedOrUpdated 47m
```
-In order to see additional addresses or extra information about the `Status` of the resource, use the following command:
+To see additional addresses or extra information about the `Status` of the resource, use the following command:
```shell
kubectl describe transportserver
-. . .
+```
+```text
Status:
Message: Configuration for default/dns-tcp was added or updated
Reason: AddedOrUpdated
State: Valid
```
-### Status Specification
+### Status specification
The following fields are reported in TransportServer status:
-{{% table %}}
+{{}}
|Field | Description | Type |
| ---| ---| --- |
-|``State`` | Current state of the resource. Can be ``Valid``, ``Warning`` or ``Invalid``. For more information, refer to the ``message`` field. | ``string`` |
-|``Reason`` | The reason of the last update. | ``string`` |
-|``Message`` | Additional information about the state. | ``string`` |
-{{% /table %}}
+| *State* | Current state of the resource. Can be ``Valid``, ``Warning`` or ``Invalid``. For more information, refer to the ``message`` field. | *string* |
+| *Reason* | The reason of the last update. | *string* |
+| *Message* | Additional information about the state. | *string* |
+{{}}
diff --git a/docs/content/configuration/handling-host-and-listener-collisions.md b/docs/content/configuration/host-and-listener-collisions.md
similarity index 53%
rename from docs/content/configuration/handling-host-and-listener-collisions.md
rename to docs/content/configuration/host-and-listener-collisions.md
index a7f2a9d767..052d60291f 100644
--- a/docs/content/configuration/handling-host-and-listener-collisions.md
+++ b/docs/content/configuration/host-and-listener-collisions.md
@@ -2,27 +2,33 @@
docs: DOCS-590
doctypes:
- ''
-title: Handling Host and Listener Collisions
+title: Host and Listener collisions
toc: true
weight: 1700
---
-This document explains how NGINX Ingress Controller handles host and listener collisions among resources.
+This document explains how F5 NGINX Ingress Controller handles host and listener collisions between resources.
+
+---
## Winner Selection Algorithm
-If multiple resources contend for the same host/listener, the Ingress Controller will pick the winner based on the `creationTimestamp` of the resources: the oldest resource will win. In case there are more than one oldest resource (their `creationTimestamp` is the same), the Ingress Controller will choose the resource with the lexicographically smallest `uid`.
+If multiple resources contend for the same host or listener, NGINX Ingress Controller will pick the winner based on the `creationTimestamp` of the resources: the oldest resource will win. In case there are more than one oldest resource (their `creationTimestamp` is the same), NGINX Ingress Controller will choose the resource with the lexicographically smallest `uid`.
+
+{{< note >}} The `creationTimestamp` and `uid` fields are part of the [ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#objectmeta-v1-meta) resource. {{< /note >}}
-Note: the `creationTimestamp` and `uid` fields are part of the resource [ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#objectmeta-v1-meta).
+---
+
+## Host collisions
-## Host Collisions
+A host collision occurs when multiple Ingress, VirtualServer, and TransportServer (configured for TLS Passthrough) resources configure the same `host`. NGINX Ingress Controller has two strategies for handling host collisions:
-A host collision occurs when multiple Ingress, VirtualServer, and TransportServer (configured for TLS Passthrough) resources configure the same `host`. The Ingress Controller supports two options for handling host collisions:
+- Choosing a single "winner" resource to handle the host.
+- Merging the configuration of the conflicting resources.
-- Choosing the winner so that only one resource handles the host.
-- Merging configuration of the conflicting resources.
+---
-### Choosing the Winner
+### Choosing the winner
Consider the following two resources:
@@ -52,16 +58,17 @@ Consider the following two resources:
. . .
```
-If a user creates both resources in the cluster, a host collision will occur. As a result, the Ingress Controller will pick the winner using the [winner selection algorithm](#winner-selection-algorithm).
+If a user creates both resources in the cluster, a host collision will occur. NGINX Ingress Controller will pick the winner using the [winner selection algorithm](#winner-selection-algorithm).
-In our example, if `cafe-virtual-server` was created first, it will win the host `cafe.example.com` and the Ingress Controller will reject `cafe-ingress`. This will be reflected in the events and in the resource's status field:
+If `cafe-virtual-server` was created first, it will win the host `cafe.example.com` and NGINX Ingress Controller will reject `cafe-ingress`. This will be reflected in the events and in the resource's status field:
```shell
kubectl describe vs cafe-virtual-server
-
-. . .
+```
+```text
+...
Status:
- . . .
+ ...
Message: Configuration for default/cafe-virtual-server was added or updated
Reason: AddedOrUpdated
State: Valid
@@ -69,32 +76,47 @@ Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 9s nginx-ingress-controller Configuration for default/cafe-virtual-server was added or updated
+```
-$ kubectl describe ingress cafe-ingress
-. . .
+```shell
+kubectl describe ingress cafe-ingress
+```
+```text
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Rejected 66s nginx-ingress-controller All hosts are taken by other resources
```
-> Note: You can configure multiple hosts for Ingress resources. As a result, it's possible that an Ingress resource can be the winner for some of its hosts and a loser for the others. For example, if `cafe-ingress` had an additional rule host rule -- `pub.example.com` -- the Ingress Controller would not reject the Ingress. Rather, it would allow `cafe-ingress` to handle `pub.example.com`.
+Similarly, if `cafe-ingress` was created first, it will win `cafe.example.com` and NGINX Ingress Controller will reject `cafe-virtual-server`.
-Similarly, if `cafe-ingress` was created first, it will win `cafe.example.com` and the Ingress Controller will reject `cafe-virtual-server`.
+{{< note >}} You can configure multiple hosts for Ingress resources, and its possible that an Ingress resource can be the winner for some of its hosts and a loser for the others.
-### Merging Configuration for the Same Host
+For example, if `cafe-ingress` had an additional rule host rule for `pub.example.com`, NGINX Ingress Controller would not reject the Ingress. Instead, it would allow `cafe-ingress` to handle `pub.example.com`. {{< /note >}}
-It is possible to merge configuration for multiple Ingress resources for the same host. One common use case for this approach is distributing resources across multiple namespaces. See the [Cross-namespace Configuration](/nginx-ingress-controller/configuration/ingress-resources/cross-namespace-configuration/) doc for more information.
+---
+
+### Merging configuration for the same host
+
+It is possible to merge configuration for multiple Ingress resources for the same host. One common use case for this approach is distributing resources across multiple namespaces.
+
+The [Cross-namespace configuration]({{< relref "configuration/ingress-resources/cross-namespace-configuration.md">}}) topic has more information.
It is *not* possible to merge the configurations for multiple VirtualServer resources for the same host. However, you can split the VirtualServers into multiple VirtualServerRoute resources, which a single VirtualServer can then reference. See the [corresponding example](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/custom-resources/cross-namespace-configuration) on GitHub.
It is *not* possible to merge configuration for multiple TransportServer resources.
-## Listener Collisions
+---
+
+## Listener collisions
-Listener collisions occur when multiple TransportServer resources (configured for TCP/UDP load balancing) configure the same `listener`. The Ingress Controller will choose the winner, which will own the listener.
+Listener collisions occur when multiple TransportServer resources (Configured for TCP/UDP load balancing) target the same `listener`.
-### Choosing the Winner
+NGINX Ingress Controller will choose the winner, which will own the listener.
+
+---
+
+### Choosing the winner
Consider the following two resources:
@@ -126,18 +148,19 @@ Consider the following two resources:
. . .
```
-If a user creates both resources in the cluster, a listener collision will occur. As a result, the Ingress Controller will pick the winner using the [winner selection algorithm](#winner-selection-algorithm).
+If a user creates both resources in the cluster, a listener collision will occur. As a result, NGINX Ingress Controller will pick the winner using the [winner selection algorithm](#winner-selection-algorithm).
-In our example, if `tcp-1` was created first, it will win the listener `dns-tcp` and the Ingress Controller will reject `tcp-2`. This will be reflected in the events and in the resource's status field:
+In our example, if `tcp-1` was created first, it will win the listener `dns-tcp` and NGINX Ingress Controller will reject `tcp-2`. This will be reflected in the events and in the resource's status field:
```shell
kubectl describe ts tcp-2
-
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Rejected 10s nginx-ingress-controller Listener dns-tcp is taken by another resource
```
-Similarly, if `tcp-2` was created first, it will win `dns-tcp` and the Ingress Controller will reject `tcp-1`.
+Similarly, if `tcp-2` was created first, it will win `dns-tcp` and NGINX Ingress Controller will reject `tcp-1`.
diff --git a/docs/content/configuration/ingress-resources/_index.md b/docs/content/configuration/ingress-resources/_index.md
index 32bdae29ad..8a2b5b282f 100644
--- a/docs/content/configuration/ingress-resources/_index.md
+++ b/docs/content/configuration/ingress-resources/_index.md
@@ -1,7 +1,7 @@
---
-title: Ingress Resources
+title: Ingress resources
description:
-weight: 1500
+weight: 200
menu:
docs:
parent: NGINX Ingress Controller
diff --git a/docs/content/configuration/ingress-resources/advanced-configuration-with-annotations.md b/docs/content/configuration/ingress-resources/advanced-configuration-with-annotations.md
index c5a6f21ad7..778f8105e9 100644
--- a/docs/content/configuration/ingress-resources/advanced-configuration-with-annotations.md
+++ b/docs/content/configuration/ingress-resources/advanced-configuration-with-annotations.md
@@ -2,16 +2,18 @@
docs: DOCS-591
doctypes:
- ''
-title: Advanced Configuration with Annotations
+title: Advanced configuration with Annotations
toc: true
-weight: 1700
+weight: 200
---
-This document explains how to enable advanced features with Annotations.
+This topic explains how to enable advanced features in F5 NGINX Ingress Controller with Annotations.
-The Ingress resource can only use basic NGINX features such as host or path-based routing and TLS termination. Advanced features like rewriting the request URI or inserting additional response headers can be enabled with Annotations. Outside of advanced features, Annotations are necessary for customizing NGINX behavior such as setting the value of connection timeouts.
+The Ingress resource can use basic NGINX features such as host or path-based routing and TLS termination. Advanced features like rewriting the request URI or inserting additional response headers can be enabled with Annotations.
-Customization is also available through the [ConfigMap]({{< relref "/configuration/global-configuration/configmap-resource.md" >}}): Annotations take priority over the ConfigMap.
+Outside of advanced features, Annotations are necessary for customizing NGINX behavior such as setting the value of connection timeouts.
+
+Customization is also available through the [ConfigMap]({{< relref "/configuration/global-configuration/configmap-resource.md" >}}) resources: Annotations take priority.
## Using Annotations
@@ -53,28 +55,29 @@ spec:
## Validation
-NGINX Ingress Controller validates the annotations of Ingress resources. If an Ingress is invalid, NGINX Ingress Controller will reject it: the Ingress will continue to exist in the cluster, but the Ingress Controller will ignore it.
+NGINX Ingress Controller validates the annotations of Ingress resources. If an Ingress is invalid, NGINX Ingress Controller will reject it: the Ingress will continue to exist in the cluster, but NGINX Ingress Controller will ignore it.
-You can check if the Ingress Controller successfully applied the configuration for an Ingress. For our example `cafe-ingress-with-annotations` Ingress, we can run:
+You can check if NGINX Ingress Controller successfully applied the configuration for an Ingress resource. For the example `cafe-ingress-with-annotations` Ingress, you can run:
```shell
kubectl describe ing cafe-ingress-with-annotations
-
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 3s nginx-ingress-controller Configuration for default/cafe-ingress-with-annotations was added or updated
```
-Note how the events section includes a Normal event with the AddedOrUpdated reason that informs us that the configuration was successfully applied.
+The events section includes a Normal event with the AddedOrUpdated reason that informs us that the configuration was successfully applied.
-If you create an invalid Ingress, the Ingress Controller will reject it and emit a Rejected event. For example, if you create an Ingress `cafe-ingress-with-annotations`, with an annotation `nginx.org/redirect-to-https` set to `yes please` instead of `true`, you will get:
+If you create an invalid Ingress, NGINX Ingress Controller will reject it and emit a Rejected event. For example, if you create an Ingress `cafe-ingress-with-annotations`, with an annotation `nginx.org/redirect-to-https` set to `yes please` instead of `true`, you will get:
```shell
kubectl describe ing cafe-ingress-with-annotations
-
-. . .
+```
+```text
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
@@ -83,141 +86,139 @@ Events:
Note how the events section includes a Warning event with the Rejected reason.
-**Note**: If you make an existing Ingress invalid, the Ingress Controller will reject it and remove the corresponding configuration from NGINX.
-
-The following Ingress annotation currently has limited validation:
+{{< note >}} If you make an existing Ingress invalid, NGINX Ingress Controller will reject it and remove the corresponding configuration from NGINX. {{< /note >}}
-- `nginx.com/jwt-token`.
+The `nginx.com/jwt-token` Ingress annotation has limited validation.
## Summary of Annotations
The table below summarizes the available annotations.
-**Note**: The annotations that start with `nginx.com` are only supported with NGINX Plus.
+{{< note >}} Annotations that start with `nginx.com` are only supported with NGINX Plus. {{< /note >}}
-### General Customization
+### General customization
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/proxy-connect-timeout`` | ``proxy-connect-timeout`` | Sets the value of the [proxy_connect_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout) and [grpc_connect_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_connect_timeout) directive. | ``60s`` | |
-|``nginx.org/proxy-read-timeout`` | ``proxy-read-timeout`` | Sets the value of the [proxy_read_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout) and [grpc_read_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_read_timeout) directive. | ``60s`` | |
-|``nginx.org/proxy-send-timeout`` | ``proxy-send-timeout`` | Sets the value of the [proxy_send_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout) and [grpc_send_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_send_timeout) directive. | ``60s`` | |
-|``nginx.org/client-max-body-size`` | ``client-max-body-size`` | Sets the value of the [client_max_body_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) directive. | ``1m`` | |
-|``nginx.org/proxy-buffering`` | ``proxy-buffering`` | Enables or disables [buffering of responses](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering) from the proxied server. | ``True`` | |
-|``nginx.org/proxy-buffers`` | ``proxy-buffers`` | Sets the value of the [proxy_buffers](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers) directive. | Depends on the platform. | |
-|``nginx.org/proxy-buffer-size`` | ``proxy-buffer-size`` | Sets the value of the [proxy_buffer_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size) and [grpc_buffer_size](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_buffer_size) directives. | Depends on the platform. | |
-|``nginx.org/proxy-max-temp-file-size`` | ``proxy-max-temp-file-size`` | Sets the value of the [proxy_max_temp_file_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_max_temp_file_size) directive. | ``1024m`` | |
-|``nginx.org/server-tokens`` | ``server-tokens`` | Enables or disables the [server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) directive. Additionally, with the NGINX Plus, you can specify a custom string value, including the empty string value, which disables the emission of the “Server” field. | ``True`` | |
-|``nginx.org/path-regex`` | N/A | Enables regular expression modifiers for Ingress path parameter. This translates to the NGINX [location](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) directive. You can specify one of these values: "case_sensitive", "case_insensitive", or "exact". The annotation is applied to the entire Ingress resource and its paths. While using Master and Minion Ingresses i.e. Mergeable Ingresses, this annotation can be specified on Minion types. The `path-regex` annotation specified on Master is ignored, and has no effect on paths defined on Minions. | N/A | [Path Regex](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/path-regex). |
-{{% /table %}}
+| *nginx.org/proxy-connect-timeout* | *proxy-connect-timeout* | Sets the value of the [proxy_connect_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_connect_timeout) and [grpc_connect_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_connect_timeout) directive. | *60s* | |
+| *nginx.org/proxy-read-timeout* | *proxy-read-timeout* | Sets the value of the [proxy_read_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout) and [grpc_read_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_read_timeout) directive. | *60s* | |
+| *nginx.org/proxy-send-timeout* | *proxy-send-timeout* | Sets the value of the [proxy_send_timeout](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout) and [grpc_send_timeout](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_send_timeout) directive. | *60s* | |
+| *nginx.org/client-max-body-size* | *client-max-body-size* | Sets the value of the [client_max_body_size](https://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) directive. | *1m* | |
+| *nginx.org/proxy-buffering* | *proxy-buffering* | Enables or disables [buffering of responses](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering) from the proxied server. | *True* | |
+| *nginx.org/proxy-buffers* | *proxy-buffers* | Sets the value of the [proxy_buffers](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers) directive. | Depends on the platform. | |
+| *nginx.org/proxy-buffer-size* | *proxy-buffer-size* | Sets the value of the [proxy_buffer_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size) and [grpc_buffer_size](https://nginx.org/en/docs/http/ngx_http_grpc_module.html#grpc_buffer_size) directives. | Depends on the platform. | |
+| *nginx.org/proxy-max-temp-file-size* | *proxy-max-temp-file-size* | Sets the value of the [proxy_max_temp_file_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_max_temp_file_size) directive. | *1024m* | |
+| *nginx.org/server-tokens* | *server-tokens* | Enables or disables the [server_tokens](https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) directive. Additionally, with the NGINX Plus, you can specify a custom string value, including the empty string value, which disables the emission of the “Server” field. | *True* | |
+| *nginx.org/path-regex* | N/A | Enables regular expression modifiers for Ingress path parameter. This translates to the NGINX [location](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) directive. You can specify one of these values: "case_sensitive", "case_insensitive", or "exact". The annotation is applied to the entire Ingress resource and its paths. While using Master and Minion Ingresses i.e. Mergeable Ingresses, this annotation can be specified on Minion types. The `path-regex` annotation specified on Master is ignored, and has no effect on paths defined on Minions. | N/A | [path-regex](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/path-regex) |
+{{}}
### Request URI/Header Manipulation
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/proxy-hide-headers`` | ``proxy-hide-headers`` | Sets the value of one or more [proxy_hide_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header) directives. Example: ``"nginx.org/proxy-hide-headers": "header-a,header-b"`` | N/A | |
-|``nginx.org/proxy-pass-headers`` | ``proxy-pass-headers`` | Sets the value of one or more [proxy_pass_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_header) directives. Example: ``"nginx.org/proxy-pass-headers": "header-a,header-b"`` | N/A | |
-|``nginx.org/rewrites`` | N/A | Configures URI rewriting using [proxy_pass](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass) directive. | N/A | [Rewrites Support](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/rewrites). |
-{{% /table %}}
+| *nginx.org/proxy-hide-headers* | *proxy-hide-headers* | Sets the value of one or more [proxy_hide_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header) directives. Example: ``"nginx.org/proxy-hide-headers": "header-a,header-b"* | N/A | |
+| *nginx.org/proxy-pass-headers* | *proxy-pass-headers* | Sets the value of one or more [proxy_pass_header](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_header) directives. Example: ``"nginx.org/proxy-pass-headers": "header-a,header-b"* | N/A | |
+| *nginx.org/rewrites* | N/A | Configures URI rewriting using [proxy_pass](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass) directive. | N/A | [rewrites](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/rewrites) |
+{{}}
### Auth and SSL/TLS
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/redirect-to-https`` | ``redirect-to-https`` | Sets the 301 redirect rule based on the value of the ``http_x_forwarded_proto`` header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of the Ingress Controller — see [115](https://github.com/nginxinc/kubernetes-ingress/issues/115) | ``False`` | |
-|``ingress.kubernetes.io/ssl-redirect`` | ``ssl-redirect`` | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | ``True`` | |
-|``nginx.org/hsts`` | ``hsts`` | Enables [HTTP Strict Transport Security (HSTS)](https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/)\ : the HSTS header is added to the responses from backends. The ``preload`` directive is included in the header. | ``False`` | |
-|``nginx.org/hsts-max-age`` | ``hsts-max-age`` | Sets the value of the ``max-age`` directive of the HSTS header. | ``2592000`` (1 month) | |
-|``nginx.org/hsts-include-subdomains`` | ``hsts-include-subdomains`` | Adds the ``includeSubDomains`` directive to the HSTS header. | ``False`` | |
-|``nginx.org/hsts-behind-proxy`` | ``hsts-behind-proxy`` | Enables HSTS based on the value of the ``http_x_forwarded_proto`` request header. Should only be used when TLS termination is configured in a load balancer (proxy) in front of the Ingress Controller. Note: to control redirection from HTTP to HTTPS configure the ``nginx.org/redirect-to-https`` annotation. | ``False`` | |
-|``nginx.org/basic-auth-secret`` | N/A | Specifies a Secret resource with a user list for HTTP Basic authentication. | N/A | |
-|``nginx.org/basic-auth-realm`` | N/A | Specifies a realm. | N/A | |
-|``nginx.com/jwt-key`` | N/A | Specifies a Secret resource with keys for validating JSON Web Tokens (JWTs). | N/A | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
-|``nginx.com/jwt-realm`` | N/A | Specifies a realm. | N/A | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
-|``nginx.com/jwt-token`` | N/A | Specifies a variable that contains a JSON Web Token. | By default, a JWT is expected in the ``Authorization`` header as a Bearer Token. | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
-|``nginx.com/jwt-login-url`` | N/A | Specifies a URL to which a client is redirected in case of an invalid or missing JWT. | N/A | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
-{{% /table %}}
+| *nginx.org/redirect-to-https* | *redirect-to-https* | Sets the 301 redirect rule based on the value of the ``http_x_forwarded_proto* header on the server block to force incoming traffic to be over HTTPS. Useful when terminating SSL in a load balancer in front of NGINX Ingress Controller — see [115](https://github.com/nginxinc/kubernetes-ingress/issues/115) | *False* | |
+| *ingress.kubernetes.io/ssl-redirect* | *ssl-redirect* | Sets an unconditional 301 redirect rule for all incoming HTTP traffic to force incoming traffic over HTTPS. | *True* | |
+| *nginx.org/hsts* | *hsts* | Enables [HTTP Strict Transport Security (HSTS)](https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/)\ : the HSTS header is added to the responses from backends. The ``preload* directive is included in the header. | *False* | |
+| *nginx.org/hsts-max-age* | *hsts-max-age* | Sets the value of the ``max-age* directive of the HSTS header. | *2592000* (1 month) | |
+| *nginx.org/hsts-include-subdomains* | *hsts-include-subdomains* | Adds the ``includeSubDomains* directive to the HSTS header. | *False* | |
+| *nginx.org/hsts-behind-proxy* | *hsts-behind-proxy* | Enables HSTS based on the value of the ``http_x_forwarded_proto* request header. Should only be used when TLS termination is configured in a load balancer (proxy) in front of NGINX Ingress Controller. Note: to control redirection from HTTP to HTTPS configure the ``nginx.org/redirect-to-https* annotation. | *False* | |
+| *nginx.org/basic-auth-secret* | N/A | Specifies a Secret resource with a user list for HTTP Basic authentication. | N/A | |
+| *nginx.org/basic-auth-realm* | N/A | Specifies a realm. | N/A | |
+| *nginx.com/jwt-key* | N/A | Specifies a Secret resource with keys for validating JSON Web Tokens (JWTs). | N/A | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
+| *nginx.com/jwt-realm* | N/A | Specifies a realm. | N/A | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
+| *nginx.com/jwt-token* | N/A | Specifies a variable that contains a JSON Web Token. | By default, a JWT is expected in the ``Authorization* header as a Bearer Token. | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
+| *nginx.com/jwt-login-url* | N/A | Specifies a URL to which a client is redirected in case of an invalid or missing JWT. | N/A | [Support for JSON Web Tokens (JWTs)](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/jwt). |
+{{}}
### Listeners
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/listen-ports`` | N/A | Configures HTTP ports that NGINX will listen on. | ``[80]`` | |
-|``nginx.org/listen-ports-ssl`` | N/A | Configures HTTPS ports that NGINX will listen on. | ``[443]`` | |
-{{% /table %}}
+| *nginx.org/listen-ports* | N/A | Configures HTTP ports that NGINX will listen on. | *[80]* | |
+| *nginx.org/listen-ports-ssl* | N/A | Configures HTTPS ports that NGINX will listen on. | *[443]* | |
+{{}}
-### Backend Services (Upstreams)
+### Backend services (Upstreams)
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/lb-method`` | ``lb-method`` | Sets the [load balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify ``"round_robin"``. | ``"random two least_conn"`` | |
-|``nginx.org/ssl-services`` | N/A | Enables HTTPS or gRPC over SSL when connecting to the endpoints of services. | N/A | [SSL Services Support](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/ssl-services). |
-|``nginx.org/grpc-services`` | N/A | Enables gRPC for services. Note: requires HTTP/2 (see ``http2`` ConfigMap key); only works for Ingresses with TLS termination enabled. | N/A | [GRPC Services Support](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/grpc-services). |
-|``nginx.org/websocket-services`` | N/A | Enables WebSocket for services. | N/A | [WebSocket support](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/websocket). |
-|``nginx.org/max-fails`` | ``max-fails`` | Sets the value of the [max_fails](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails) parameter of the ``server`` directive. | ``1`` | |
-|``nginx.org/max-conns`` | N\A | Sets the value of the [max_conns](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_conns) parameter of the ``server`` directive. | ``0`` | |
-|``nginx.org/upstream-zone-size`` | ``upstream-zone-size`` | Sets the size of the shared memory [zone](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone) for upstreams. For NGINX, the special value 0 disables the shared memory zones. For NGINX Plus, shared memory zones are required and cannot be disabled. The special value 0 will be ignored. | ``256K`` | |
-|``nginx.org/fail-timeout`` | ``fail-timeout`` | Sets the value of the [fail_timeout](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#fail_timeout) parameter of the ``server`` directive. | ``10s`` | |
-|``nginx.com/sticky-cookie-services`` | N/A | Configures session persistence. | N/A | [Session Persistence](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/session-persistence). |
-|``nginx.org/keepalive`` | ``keepalive`` | Sets the value of the [keepalive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive. Note that ``proxy_set_header Connection "";`` is added to the generated configuration when the value > 0. | ``0`` | |
-|``nginx.com/health-checks`` | N/A | Enables active health checks. | ``False`` | [Support for Active Health Checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks). |
-|``nginx.com/health-checks-mandatory`` | N/A | Configures active health checks as mandatory. | ``False`` | [Support for Active Health Checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks). |
-|``nginx.com/health-checks-mandatory-queue`` | N/A | When active health checks are mandatory, creates a queue where incoming requests are temporarily stored while NGINX Plus is checking the health of the endpoints after a configuration reload. | ``0`` | [Support for Active Health Checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks). |
-|``nginx.com/slow-start`` | N/A | Sets the upstream server [slow-start period](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#server-slow-start). By default, slow-start is activated after a server becomes [available](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/#passive-health-checks) or [healthy](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/#active-health-checks). To enable slow-start for newly-added servers, configure [mandatory active health checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks). | ``"0s"`` | |
-|``nginx.org/use-cluster-ip`` | N/A | Enables using the Cluster IP and port of the service instead of the default behavior of using the IP and port of the pods. When this field is enabled, the fields that configure NGINX behavior related to multiple upstream servers (like ``lb-method`` and ``next-upstream``) will have no effect, as NGINX Ingress Controller will configure NGINX with only one upstream server that will match the service Cluster IP. | ``False`` | |
-{{% /table %}}
+| *nginx.org/lb-method* | *lb-method* | Sets the [load balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify ``"round_robin"``. | *"random two least_conn"* | |
+| *nginx.org/ssl-services* | N/A | Enables HTTPS or gRPC over SSL when connecting to the endpoints of services. | N/A | [ssl-services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/ssl-services) |
+| *nginx.org/grpc-services* | N/A | Enables gRPC for services. Note: requires HTTP/2 (see ``http2* ConfigMap key); only works for Ingresses with TLS termination enabled. | N/A | [grpc-services](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/grpc-services) |
+| *nginx.org/websocket-services* | N/A | Enables WebSocket for services. | N/A | [websocket](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/websocket) |
+| *nginx.org/max-fails* | *max-fails* | Sets the value of the [max_fails](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails) parameter of the ``server* directive. | *1* | |
+| *nginx.org/max-conns* | N\A | Sets the value of the [max_conns](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_conns) parameter of the ``server* directive. | *0* | |
+| *nginx.org/upstream-zone-size* | *upstream-zone-size* | Sets the size of the shared memory [zone](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#zone) for upstreams. For NGINX, the special value 0 disables the shared memory zones. For NGINX Plus, shared memory zones are required and cannot be disabled. The special value 0 will be ignored. | *256K* | |
+| *nginx.org/fail-timeout* | *fail-timeout* | Sets the value of the [fail_timeout](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#fail_timeout) parameter of the ``server* directive. | *10s* | |
+| *nginx.com/sticky-cookie-services* | N/A | Configures session persistence. | N/A | [session-persistence](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/session-persistence) |
+| *nginx.org/keepalive* | *keepalive* | Sets the value of the [keepalive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive. Note that ``proxy_set_header Connection "";* is added to the generated configuration when the value > 0. | *0* | |
+| *nginx.com/health-checks* | N/A | Enables active health checks. | *False* | [health-checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks) |
+| *nginx.com/health-checks-mandatory* | N/A | Configures active health checks as mandatory. | *False* | [health-checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks) |
+| *nginx.com/health-checks-mandatory-queue* | N/A | When active health checks are mandatory, creates a queue where incoming requests are temporarily stored while NGINX Plus is checking the health of the endpoints after a configuration reload. | *0* | [health-checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks) |
+| *nginx.com/slow-start* | N/A | Sets the upstream server [slow-start period](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#server-slow-start). By default, slow-start is activated after a server becomes [available](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/#passive-health-checks) or [healthy](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-health-check/#active-health-checks). To enable slow-start for newly-added servers, configure [mandatory active health checks](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/health-checks). | *"0s"* | |
+| *nginx.org/use-cluster-ip* | N/A | Enables using the Cluster IP and port of the service instead of the default behavior of using the IP and port of the pods. When this field is enabled, the fields that configure NGINX behavior related to multiple upstream servers (like ``lb-method* and ``next-upstream``) will have no effect, as NGINX Ingress Controller will configure NGINX with only one upstream server that will match the service Cluster IP. | *False* | |
+{{}}
### Rate limiting
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/limit-req-rate`` | N/A | Enables request-rate-limiting for this ingress by creating a [limit_req_zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone) and matching [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) for each location. All servers/locations of one ingress share the same zone. Must have unit r/s or r/m. | N/A | 200r/s |
-|``nginx.org/limit-req-key`` | N/A | The key to which the rate limit is applied. Can contain text, variables, or a combination of them. Variables must be surrounded by ${}. | ${binary_remote_addr} | ${binary_remote_addr} |
-|``nginx.org/limit-req-zone-size`` | N/A | Configures the size of the created [limit_req_zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone). | 10m | 20m |
-|``nginx.org/limit-req-delay`` | N/A | Configures the delay-parameter of the [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) directive. | 0 | 100 |
-|``nginx.org/limit-req-no-delay`` | N/A | Configures the nodelay-parameter of the [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) directive. | false | true |
-|``nginx.org/limit-req-burst`` | N/A | Configures the burst-parameter of the [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) directive. | N/A | 100 |
-|``nginx.org/limit-req-dry-run`` | N/A | Enables the dry run mode. In this mode, the rate limit is not actually applied, but the number of excessive requests is accounted as usual in the shared memory zone. | false | true |
-|``nginx.org/limit-req-log-level`` | N/A | Sets the desired logging level for cases when the server refuses to process requests due to rate exceeding, or delays request processing. Allowed values are info, notice, warn or error. | error | info |
-|``nginx.org/limit-req-reject-code`` | N/A | Sets the status code to return in response to rejected requests. Must fall into the range 400..599. | 429 | 503 |
-|``nginx.org/limit-req-scale`` | N/A | Enables a constant rate-limit by dividing the configured rate by the number of nginx-ingress pods currently serving traffic. This adjustment ensures that the rate-limit remains consistent, even as the number of nginx-pods fluctuates due to autoscaling. Note: This will not work properly if requests from a client are not evenly distributed accross all ingress pods (sticky sessions, long lived TCP-Connections with many requests etc.). In such cases using NGINX+'s zone-sync feature instead would give better results. | false | true |
-{{% /table %}}
-
-### Snippets and Custom Templates
-
-{{% table %}}
+| *nginx.org/limit-req-rate* | N/A | Enables request-rate-limiting for this ingress by creating a [limit_req_zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone) and matching [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) for each location. All servers/locations of one ingress share the same zone. Must have unit r/s or r/m. | N/A | 200r/s |
+| *nginx.org/limit-req-key* | N/A | The key to which the rate limit is applied. Can contain text, variables, or a combination of them. Variables must be surrounded by ${}. | ${binary_remote_addr} | ${binary_remote_addr} |
+| *nginx.org/limit-req-zone-size* | N/A | Configures the size of the created [limit_req_zone](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req_zone). | 10m | 20m |
+| *nginx.org/limit-req-delay* | N/A | Configures the delay-parameter of the [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) directive. | 0 | 100 |
+| *nginx.org/limit-req-no-delay* | N/A | Configures the nodelay-parameter of the [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) directive. | false | true |
+| *nginx.org/limit-req-burst* | N/A | Configures the burst-parameter of the [limit_req](https://nginx.org/en/docs/http/ngx_http_limit_req_module.html#limit_req) directive. | N/A | 100 |
+| *nginx.org/limit-req-dry-run* | N/A | Enables the dry run mode. In this mode, the rate limit is not actually applied, but the number of excessive requests is accounted as usual in the shared memory zone. | false | true |
+| *nginx.org/limit-req-log-level* | N/A | Sets the desired logging level for cases when the server refuses to process requests due to rate exceeding, or delays request processing. Allowed values are info, notice, warn or error. | error | info |
+| *nginx.org/limit-req-reject-code* | N/A | Sets the status code to return in response to rejected requests. Must fall into the range 400..599. | 429 | 503 |
+| *nginx.org/limit-req-scale* | N/A | Enables a constant rate-limit by dividing the configured rate by the number of nginx-ingress pods currently serving traffic. This adjustment ensures that the rate-limit remains consistent, even as the number of nginx-pods fluctuates due to autoscaling. Note: This will not work properly if requests from a client are not evenly distributed accross all ingress pods (sticky sessions, long lived TCP-Connections with many requests etc.). In such cases using NGINX+'s zone-sync feature instead would give better results. | false | true |
+{{}}
+
+### Snippets and custom templates
+
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``nginx.org/location-snippets`` | ``location-snippets`` | Sets a custom snippet in location context. | N/A | |
-|``nginx.org/server-snippets`` | ``server-snippets`` | Sets a custom snippet in server context. | N/A | |
-{{% /table %}}
+| *nginx.org/location-snippets* | *location-snippets* | Sets a custom snippet in location context. | N/A | |
+| *nginx.org/server-snippets* | *server-snippets* | Sets a custom snippet in server context. | N/A | |
+{{}}
-### App Protect {#app-protect}
+### App Protect WAF {#app-protect}
-**Note**: The App Protect annotations only work if App Protect WAF module is [installed](/nginx-ingress-controller/app-protect/installation/).
+{{< note >}} The App Protect annotations only work if the App Protect WAF module is [installed]({{< relref "installation/integrations/app-protect-waf/installation.md" >}}). {{< /note >}}
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``appprotect.f5.com/app-protect-policy`` | N/A | The name of the App Protect Policy for the Ingress Resource. Format is ``namespace/name``. If no namespace is specified, the same namespace of the Ingress Resource is used. If not specified but ``appprotect.f5.com/app-protect-enable`` is true, a default policy id applied. If the referenced policy resource does not exist, or policy is invalid, this annotation will be ignored, and the default policy will be applied. | N/A | [Example for App Protect](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf). |
-|``appprotect.f5.com/app-protect-enable`` | N/A | Enable App Protect for the Ingress Resource. | ``False`` | [Example for App Protect](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf). |
-|``appprotect.f5.com/app-protect-security-log-enable`` | N/A | Enable the [security log](/nginx-app-protect/troubleshooting/#app-protect-logging-overview) for App Protect. | ``False`` | [Example for App Protect](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf). |
-|``appprotect.f5.com/app-protect-security-log`` | N/A | The App Protect log configuration for the Ingress Resource. Format is ``namespace/name``. If no namespace is specified, the same namespace as the Ingress Resource is used. If not specified the default is used which is: filter: ``illegal``, format: ``default``. Multiple configurations can be specified in a comma separated list. Both log configurations and destinations list (see below) must be of equal length. Configs and destinations are paired by the list indices. | N/A | [Example for App Protect](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf). |
-|``appprotect.f5.com/app-protect-security-log-destination`` | N/A | The destination of the security log. For more information check the [DESTINATION argument](/nginx-app-protect/troubleshooting/#app-protect-logging-overview). Multiple destinations can be specified in a comma-separated list. Both log configurations and destinations list (see above) must be of equal length. Configs and destinations are paired by the list indices. | ``syslog:server=localhost:514`` | [Example for App Protect](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf). |
-{{% /table %}}
+| *appprotect.f5.com/app-protect-policy* | N/A | The name of the App Protect Policy for the Ingress Resource. Format is ``namespace/name``. If no namespace is specified, the same namespace of the Ingress Resource is used. If not specified but ``appprotect.f5.com/app-protect-enable* is true, a default policy id applied. If the referenced policy resource does not exist, or policy is invalid, this annotation will be ignored, and the default policy will be applied. | N/A | [app-protect-waf](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf) |
+| *appprotect.f5.com/app-protect-enable* | N/A | Enable App Protect for the Ingress Resource. | *False* | [app-protect-waf](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf) |
+| *appprotect.f5.com/app-protect-security-log-enable* | N/A | Enable the [security log](/nginx-app-protect/troubleshooting/#app-protect-logging-overview) for App Protect. | *False* | [app-protect-waf](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf) |
+| *appprotect.f5.com/app-protect-security-log* | N/A | The App Protect log configuration for the Ingress Resource. Format is ``namespace/name``. If no namespace is specified, the same namespace as the Ingress Resource is used. If not specified the default is used which is: filter: ``illegal``, format: ``default``. Multiple configurations can be specified in a comma separated list. Both log configurations and destinations list (see below) must be of equal length. Configs and destinations are paired by the list indices. | N/A | [app-protect-waf](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf) |
+| *appprotect.f5.com/app-protect-security-log-destination* | N/A | The destination of the security log. For more information check the [DESTINATION argument](/nginx-app-protect/troubleshooting/#app-protect-logging-overview). Multiple destinations can be specified in a comma-separated list. Both log configurations and destinations list (see above) must be of equal length. Configs and destinations are paired by the list indices. | *syslog:server=localhost:514* | [app-protect-waf](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-waf) |
+{{}}
### App Protect DoS
-**Note**: The App Protect DoS annotations only work if App Protect DoS module is [installed](/nginx-ingress-controller/app-protect-dos/installation/).
+{{< note >}} The App Protect DoS annotations only work if the App Protect DoS module is [installed]({{< relref "installation/integrations/app-protect-dos/installation.md" >}}). {{< /note >}}
-{{% table %}}
+{{}}
|Annotation | ConfigMap Key | Description | Default | Example |
| ---| ---| ---| ---| --- |
-|``appprotectdos.f5.com/app-protect-dos-resource`` | N/A | Enable App Protect DoS for the Ingress Resource by specifying a [DosProtectedResource](/nginx-ingress-controller/app-protect-dos/dos-protected/). | N/A | [Example for App Protect DoS](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-dos). |
-{{% /table %}}
+| *appprotectdos.f5.com/app-protect-dos-resource* | N/A | Enable App Protect DoS for the Ingress Resource by specifying a [DosProtectedResource]({{< relref "installation/integrations/app-protect-dos/dos-protected.md" >}}). | N/A | [app-protect-dos](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/app-protect-dos) |
+{{}}
diff --git a/docs/content/configuration/ingress-resources/advanced-configuration-with-snippets.md b/docs/content/configuration/ingress-resources/advanced-configuration-with-snippets.md
index 6001d18e4f..8b7006acbe 100644
--- a/docs/content/configuration/ingress-resources/advanced-configuration-with-snippets.md
+++ b/docs/content/configuration/ingress-resources/advanced-configuration-with-snippets.md
@@ -2,16 +2,34 @@
docs: DOCS-592
doctypes:
- ''
-title: Advanced Configuration with Snippets
+title: Advanced configuration with Snippets
toc: true
-weight: 1800
+weight: 400
---
-Snippets allow you to insert raw NGINX config into different contexts of the NGINX configurations that NGINX Ingress Controller generates. Snippets are intended for advanced NGINX users who need more control over the generated NGINX configuration, and can be used in cases where Annotations and ConfigMap entries would not apply.
+Snippets allow you to insert raw NGINX config into different contexts of the NGINX configurations that F5 NGINX Ingress Controller generates.
-Snippets are also available through the [ConfigMap]({{< relref "/configuration/global-configuration/configmap-resource.md" >}})
+Snippets are intended for advanced NGINX users who need more control over the generated NGINX configuration, and can be used in cases where Annotations and ConfigMap entries would not apply.
-## Using Snippets
+
+
+## Disadvantages of snippets
+
+Snippets are configured [using Annotations]({{< relref "configuration/ingress-resources/advanced-configuration-with-annotations.md#snippets-and-custom-templates" >}}), but are disabled by default due to their complexity. They are also available through the [ConfigMap]({{< relref "/configuration/global-configuration/configmap-resource.md#snippets-and-custom-templates" >}}) resource.
+
+To use snippets, set the [`enable-snippets`]({{< relref "configuration/global-configuration/command-line-arguments.md#cmdoption-enable-snippets" >}}) command-line argument.
+
+Snippets have the following disadvantages:
+
+- *Complexity*. Snippets require you to:
+ - Understand NGINX configuration primitives and implement a correct NGINX configuration.
+ - Understand how NGINX Ingress Controller generates NGINX configuration so that a snippet doesn't interfere with the other features in the configuration.
+- *Decreased robustness*. An incorrect snippet can invalidate NGINX configuration, causing reload failures. Until the snippet is fixed, it will prevent any new configuration updates, including updates for the other Ingress resources.
+- *Security implications*. Snippets give access to NGINX configuration primitives, which are not validated by NGINX Ingress Controller. For example, a snippet can configure NGINX to serve the TLS certificates and keys used for TLS termination for Ingress resources.
+
+{{< note >}} If the NGINX configuration includes an invalid snippet, NGINX will continue to operate with the last valid configuration. {{< /note >}}
+
+## Using snippets
The example below shows how to use snippets to customize the NGINX configuration template using annotations.
@@ -48,7 +66,9 @@ spec:
number: 80
```
-Generated NGINX configuration:
+These snippets generate the following NGINX configuration:
+
+{{< note >}} The example is shortened for conciseness. {{< /note >}}
```nginx
server {
@@ -79,32 +99,13 @@ server {
}
```
-**Note**: The generated configs are truncated for the clarity of the example.
-
-## Summary of Snippets
-
-See the [snippets annotations](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations/#snippets-and-custom-templates) documentation for more information.
-However, because of the disadvantages described below, snippets are disabled by default. To use snippets, set the [`enable-snippets`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-enable-snippets) command-line argument.
-
-## Disadvantages of Using Snippets
-
-Snippets have the following disadvantages:
-
-- *Complexity*. To use snippets, you will need to:
- - Understand NGINX configuration primitives and implement a correct NGINX configuration.
- - Understand how the IC generates NGINX configuration so that a snippet doesn't interfere with the other features in the configuration.
-- *Decreased robustness*. An incorrect snippet makes the NGINX config invalid, which causes reload failures. This will prevent any new configuration updates, including updates for the other Ingress resources, until the snippet is fixed.
-- *Security implications*. Snippets give access to NGINX configuration primitives and those primitives are not validated by the Ingress Controller. For example, a snippet can configure NGINX to serve the TLS certificates and keys used for TLS termination for Ingress resources.
-
-> **Note**: If the NGINX config includes an invalid snippet, NGINX will continue to operate with the latest valid configuration.
-
## Troubleshooting
-If a snippet includes an invalid NGINX configuration, the Ingress Controller will fail to reload NGINX. The error will be reported in the Ingress Controller logs and an event with the error will be associated with the Ingress resource:
+If a snippet includes an invalid NGINX configuration, NGINX Ingress Controller will fail to reload NGINX. The error will be reported in NGINX Ingress Controller logs and an event with the error will be associated with the Ingress resource:
An example of an error from the logs:
-```shell
+```text
[emerg] 31#31: unknown directive "badd_header" in /etc/nginx/conf.d/default-cafe-ingress-with-snippets.conf:54
Event(v1.ObjectReference{Kind:"Ingress", Namespace:"default", Name:"cafe-ingress-with-snippets", UID:"f9656dc9-63a6-41dd-a499-525b0e0309bb", APIVersion:"extensions/v1beta1", ResourceVersion:"2322030", FieldPath:""}): type: 'Warning' reason: 'AddedOrUpdatedWithError' Configuration for default/cafe-ingress-with-snippets was added or updated, but not applied: Error reloading NGINX for default/cafe-ingress-with-snippets: nginx reload failed: Command /usr/sbin/nginx -s reload stdout: ""
stderr: "nginx: [emerg] unknown directive \"badd_header\" in /etc/nginx/conf.d/default-cafe-ingress-with-snippets.conf:54\n"
@@ -113,7 +114,7 @@ finished with error: exit status 1
An example of an event with an error (you can view events associated with the Ingress by running `kubectl describe -n nginx-ingress ingress nginx-ingress`):
-```shell
+```text
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
diff --git a/docs/content/configuration/ingress-resources/basic-configuration.md b/docs/content/configuration/ingress-resources/basic-configuration.md
index 8a04087311..c22fa376c4 100644
--- a/docs/content/configuration/ingress-resources/basic-configuration.md
+++ b/docs/content/configuration/ingress-resources/basic-configuration.md
@@ -1,14 +1,13 @@
---
-description: The example in this document shows a basic Ingress resource definition.
docs: DOCS-593
doctypes:
- ''
-title: Basic Configuration
+title: Basic configuration
toc: true
-weight: 1600
+weight: 100
---
-This document shows a basic Ingress resource definition which load balances requests for two services as part of a single application.
+This document shows a basic Ingress resource definition for F5 NGINX Ingress Controller. It load balances requests for two services as part of a single application.
```yaml
apiVersion: networking.k8s.io/v1
@@ -43,20 +42,21 @@ spec:
Here is a breakdown of what this Ingress resource definition means:
- The `metadata.name` field defines the name of the resource `cafe‑ingress`.
-- In the `spec.tls` field we set up SSL/TLS termination:
- - In the `secretName`, we reference a secret resource by its name, `cafe‑secret`. The secret must belong to the same namespace as the Ingress, it must be of the type ``kubernetes.io/tls`` and contain keys named ``tls.crt`` and ``tls.key`` that hold the certificate and private key as described [here](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls>). If the secret doesn't exist or is invalid, NGINX will break any attempt to establish a TLS connection to the hosts to which the secret is applied.
- - In the `hosts` field, we apply the certificate and key to our `cafe.example.com` host.
-- In the `spec.rules` field, we define a host with domain name `cafe.example.com`.
-- In the `paths` field, we define two path‑based rules:
+- The `spec.tls` field sets up SSL/TLS termination:
+ - The `hosts` field applies the certificate and key to the `cafe.example.com` host.
+ - The `secretName` references a secret resource by its name, `cafe‑secret`. The secret must belong to the same namespace as the Ingress, of the type ``kubernetes.io/tls`` and contain keys named ``tls.crt`` and ``tls.key`` that hold the certificate and private key as described [here](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls>). If the secret doesn't exist or is invalid, NGINX will break any attempt to establish a TLS connection to the hosts to which the secret is applied.
+- The `spec.rules` field defines a host with the domain name `cafe.example.com`.
+- The `paths` field defines two path‑based rules:
- The rule with the path `/tea` instructs NGINX to distribute the requests with the `/tea` URI among the pods of the *tea* service, which is deployed with the name `tea‑svc` in the cluster.
- The rule with the path `/coffee` instructs NGINX to distribute the requests with the `/coffee` URI among the pods of the *coffee* service, which is deployed with the name `coffee‑svc` in the cluster.
- Both rules instruct NGINX to distribute the requests to `port 80` of the corresponding service (the `servicePort` field).
-> For complete instructions on deploying the Ingress and Secret resources in the cluster, see the [complete example](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/complete-example) in our GitHub repository.
+To learn more about the Ingress resource, view [the official Kubernetes documentation for Ingress resources](https://kubernetes.io/docs/concepts/services-networking/ingress/).
-> To learn more about the Ingress resource, see the [Ingress resource documentation](https://kubernetes.io/docs/concepts/services-networking/ingress/) in the Kubernetes docs.
+{{< note >}} For complete instructions on deploying Ingress and Secret resources in the cluster, see the [complete example](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/complete-example) in the GitHub repository. {{< /note >}}
-## New Features Available in Kubernetes 1.18 and Above
+
+## New features available in Kubernetes 1.18
Starting from Kubernetes 1.18, you can use the following new features:
@@ -103,19 +103,23 @@ Starting from Kubernetes 1.18, you can use the following new features:
. . .
```
- When using this filed you need to create the `IngressClass` resource with the corresponding `name`. See Step 3 *Create an IngressClass resource* of the [Create Common Resources](/nginx-ingress-controller/installation/installation-with-manifests/#2-create-common-resources) section.
+ When using this field you need to create the `IngressClass` resource with the corresponding `name`. View the [Create common resources]({{< relref "installation/installing-nic/installation-with-manifests.md#create-common-resources" >}}) section of the Installation with Manifests topic for more information.
## Restrictions
NGINX Ingress Controller imposes the following restrictions on Ingress resources:
- When defining an Ingress resource, the `host` field is required.
-- The `host` value needs to be unique among all Ingress and VirtualServer resources unless the Ingress resource is a [mergeable minion](/nginx-ingress-controller/configuration/ingress-resources/cross-namespace-configuration/). See also [Handling Host and Listener Collisions](/nginx-ingress-controller/configuration/handling-host-and-listener-collisions).
+- The `host` value needs to be unique among all Ingress and VirtualServer resources unless the Ingress resource is a [mergeable minion]({{< relref "configuration/ingress-resources/cross-namespace-configuration.md" >}}). View the [Host and Listener collisions]({{< relref "configuration/host-and-listener-collisions.md" >}}) topic for more information.
- The `path` field in `spec.rules[].http.paths[]` is required for `Exact` and `Prefix` `pathTypes`.
- The ImplementationSpecific `pathType` is treated as equivalent to `Prefix` `pathType`, with the exception that when this `pathType` is configured, the `path` field in `spec.rules[].http.paths[]` is not mandatory. `path` defaults to `/` if not set but the `pathType` is set to ImplementationSpecific.
-## Advanced Configuration
+## Advanced configuration
+
+NGINX Ingress Controller generates NGINX configuration by executing a template file that contains the configuration options. These options are set with the Ingress resource and NGINX Ingress Controller's ConfigMap. The Ingress resource only allows you to use basic NGINX features: host and path-based routing and TLS termination.
+
+Advanced features like rewriting the request URI or inserting additional response headers are available through annotations. View the [Advanced configuration with Annotations]({{< relref "configuration/ingress-resources/advanced-configuration-with-annotations.md" >}}) topic for more information.
-The Ingress resource only allows you to use basic NGINX features -- host and path-based routing and TLS termination. Advanced features like rewriting the request URI or inserting additional response headers are available through annotations. See the [Advanced Configuration with Annotations](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations) doc.
+Advanced NGINX users who require more control over the generated NGINX configurations can use snippets to insert raw NGINX config. View the [Advanced configuration with Snippets]({{< relref "configuration/ingress-resources/advanced-configuration-with-snippets" >}}) topic for more information.
-The Ingress Controller generates NGINX configuration by executing a template file that contains configuration options. These options are set via the Ingress resource and the Ingress Controller's ConfigMap. Advanced NGINX users who require more control over the generated NGINX configurations can use snippets to insert raw NGINX config. See [Advanced Configuration with Snippets](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-snippets) for more information. Additionally, it is possible to customize the template. See [Custom Templates](/nginx-ingress-controller/configuration/global-configuration/custom-templates/) for instructions.
+Additionally, it is possible to customize the template, described in the [Custom templates]({{< relref "/configuration/global-configuration/custom-templates.md" >}}) topic.
diff --git a/docs/content/configuration/ingress-resources/cross-namespace-configuration.md b/docs/content/configuration/ingress-resources/cross-namespace-configuration.md
index 982b802bff..49a62416c3 100644
--- a/docs/content/configuration/ingress-resources/cross-namespace-configuration.md
+++ b/docs/content/configuration/ingress-resources/cross-namespace-configuration.md
@@ -2,12 +2,12 @@
docs: DOCS-594
doctypes:
- ''
-title: Cross-namespace Configuration
+title: Cross-namespace configuration
toc: true
-weight: 2000
+weight: 500
---
-This document explains how to spread Ingress configuration across different namespaces.
+This topic explains how to spread Ingress configuration across different namespaces in F5 NGINX Ingress Controller.
You can spread the Ingress configuration for a common host across multiple Ingress resources using Mergeable Ingress resources. Such resources can belong to the *same* or *different* namespaces. This enables easier management when using a large number of paths. See the [Mergeable Ingress Resources](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/mergeable-ingress-types) example in our GitHub repo.
diff --git a/docs/content/configuration/ingress-resources/custom-annotations.md b/docs/content/configuration/ingress-resources/custom-annotations.md
index 7afccfd3d4..bed0785cf8 100644
--- a/docs/content/configuration/ingress-resources/custom-annotations.md
+++ b/docs/content/configuration/ingress-resources/custom-annotations.md
@@ -2,14 +2,16 @@
docs: DOCS-595
doctypes:
- ''
-title: Custom Annotations
+title: Custom annotations
toc: true
-weight: 1900
+weight: 300
---
+This topic explains how you can use custom annotations with F5 NGINX Ingress Controller.
+
Custom annotations enable you to quickly extend the Ingress resource to support many advanced features of NGINX, such as rate limiting, caching, etc.
-## What are Custom Annotations
+## Overview
NGINX Ingress Controller supports a number of annotations for the Ingress resource that fine tune NGINX configuration (for example, connection timeouts) or enable additional features (for example, JWT validation). The complete list of annotations is available [here](/nginx-ingress-controller/configuration/ingress-resources/advanced-configuration-with-annotations).
diff --git a/docs/content/configuration/policy-resource.md b/docs/content/configuration/policy-resource.md
index 1983f0c1ce..6aa2c787c4 100644
--- a/docs/content/configuration/policy-resource.md
+++ b/docs/content/configuration/policy-resource.md
@@ -2,9 +2,9 @@
docs: DOCS-596
doctypes:
- ''
-title: Policy Resource
+title: Policy resources
toc: true
-weight: 1800
+weight: 600
---
The Policy resource allows you to configure features like access control and rate-limiting, which you can add to your [VirtualServer and VirtualServerRoute resources](/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/).
diff --git a/docs/content/configuration/security.md b/docs/content/configuration/security.md
index fdc7d12424..5a869a1840 100644
--- a/docs/content/configuration/security.md
+++ b/docs/content/configuration/security.md
@@ -4,10 +4,10 @@ doctypes:
- ''
title: Security recommendations
toc: true
-weight: 1500
+weight: 300
---
-NGINX Ingress Controller follows Kubernetes best practices: this page outlines configuration specific to NGINX Ingress Controller you may require, including links to examples in the [GitHub repository](https://github.com/nginxinc/kubernetes-ingress/tree/release-3.5).
+F5 NGINX Ingress Controller follows Kubernetes best practices: this page outlines configuration specific to NGINX Ingress Controller you may require, including links to examples in the [GitHub repository](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples).
For general guidance, we recommend the official Kubernetes documentation for [Securing a Cluster](https://kubernetes.io/docs/tasks/administer-cluster/securing-a-cluster/).
@@ -17,13 +17,10 @@ For general guidance, we recommend the official Kubernetes documentation for [Se
Kubernetes uses [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) to control the resources and operations available to different types of users.
-The Ingress Controller is deployed within a Kubernetes environment, this environment must be secured.
-Kubernetes uses [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/) to control the resources and operations available to different types of users.
-The Ingress Controller requires a service account which is configured using RBAC.
-We strongly recommend using the [RBAC configuration](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/deployments/rbac/rbac.yaml) provided in our standard deployment configuration. It is configured with the least amount of privilege required for the Ingress Controller to work.
+NGINX Ingress Controller requires RBAC to configure a [ServiceUser](https://kubernetes.io/docs/concepts/security/service-accounts/#default-service-accounts), and provides least privilege access in its standard deployment configurations:
-We strongly recommend inspecting the RBAC configuration for [Manifests](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/deployments/rbac/rbac.yaml)
-or for [Helm](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/charts/nginx-ingress/templates/clusterrole.yaml) to understand what access the Ingress Controller service account has and to which resources. For example, by default the service account has access to all Secret resources in the cluster.
+- [Helm](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/deployments/rbac/rbac.yaml)
+- [Manifests](https://github.com/nginxinc/kubernetes-ingress/blob/v3.5.2/deployments/rbac/rbac.yaml)
By default, the ServiceAccount has access to all Secret resources in the cluster.
@@ -96,7 +93,7 @@ Snippets are disabled by default. To use snippets, set the [**enable-snippets**]
For more information, read the following:
-- [Advanced Configuration using Snippets]({{< relref "/configuration/ingress-resources/advanced-configuration-with-snippets.md" >}})
+- [Advanced configuration using Snippets]({{< relref "/configuration/ingress-resources/advanced-configuration-with-snippets.md" >}})
- [Using Snippets with VirtualServer/VirtualServerRoute]({{< relref "configuration/virtualserver-and-virtualserverroute-resources.md#using-snippets" >}})
- [Using Snippets with TransportServer]({{< relref "/configuration/transportserver-resource.md#using-snippets" >}})
-- [ConfigMap Snippets and Custom Templates]({{< relref "configuration/global-configuration/configmap-resource.md#snippets-and-custom-templates" >}})
+- [ConfigMap snippets and custom templates]({{< relref "configuration/global-configuration/configmap-resource.md#snippets-and-custom-templates" >}})
diff --git a/docs/content/configuration/transportserver-resource.md b/docs/content/configuration/transportserver-resource.md
index 06bcf0227e..8257f87f93 100644
--- a/docs/content/configuration/transportserver-resource.md
+++ b/docs/content/configuration/transportserver-resource.md
@@ -2,19 +2,21 @@
docs: DOCS-598
doctypes:
- ''
-title: TransportServer Resource
+title: TransportServer resources
toc: true
-weight: 1900
+weight: 700
---
+This document is reference material for the TransportServer resource used by F5 NGINX Ingress Controller.
+
The TransportServer resource allows you to configure TCP, UDP, and TLS Passthrough load balancing. The resource is implemented as a [Custom Resource](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
-This document is the reference documentation for the TransportServer resource. To see additional examples of using the resource for specific use cases, go to the [examples/custom-resources](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/custom-resources) folder in our GitHub repo.
+The GitHub repository has [examples of the resources](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/custom-resources) for specific use cases.
## Prerequisites
-- For TCP and UDP, the TransportServer resource must be used in conjunction with the [GlobalConfiguration resource](/nginx-ingress-controller/configuration/global-configuration/globalconfiguration-resource), which must be created separately.
-- For TLS Passthrough, make sure to enable the [`-enable-tls-passthrough`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-enable-tls-passthrough) command-line argument of the Ingress Controller.
+- For TCP and UDP, the TransportServer resource must be used in conjunction with the [GlobalConfiguration resource]({{< relref "configuration/global-configuration/globalconfiguration-resource.md" >}}), which must be created separately.
+- For TLS Passthrough, make sure to enable the [`-enable-tls-passthrough`]({{< relref "configuration/global-configuration/command-line-arguments#cmdoption-enable-tls-passthrough.md" >}}) command-line argument of NGINX Ingress Controller.
## TransportServer Specification
@@ -83,7 +85,7 @@ The TransportServer resource defines load balancing configuration for TCP, UDP,
pass: secure-app
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``listener`` | The listener on NGINX that will accept incoming connections/datagrams. | [listener](#listener) | Yes |
@@ -95,13 +97,13 @@ The TransportServer resource defines load balancing configuration for TCP, UDP,
|``ingressClassName`` | Specifies which Ingress Controller must handle the TransportServer resource. | ``string`` | No |
|``streamSnippets`` | Sets a custom snippet in the ``stream`` context. | ``string`` | No |
|``serverSnippets`` | Sets a custom snippet in the ``server`` context. | ``string`` | No |
-{{% /table %}}
+{{}}
\* -- Required for TLS Passthrough load balancing.
### Listener
-The listener field references a listener that NGINX will use to accept incoming traffic for the TransportServer. For TCP and UDP, the listener must be defined in the [GlobalConfiguration resource](/nginx-ingress-controller/configuration/global-configuration/globalconfiguration-resource). When referencing a listener, both the name and the protocol must match. For TLS Passthrough, use the built-in listener with the name `tls-passthrough` and the protocol `TLS_PASSTHROUGH`.
+The listener field references a listener that NGINX will use to accept incoming traffic for the TransportServer. For TCP and UDP, the listener must be defined in the [GlobalConfiguration resource]({{< relref "configuration/global-configuration/globalconfiguration-resource.md" >}}). When referencing a listener, both the name and the protocol must match. For TLS Passthrough, use the built-in listener with the name `tls-passthrough` and the protocol `TLS_PASSTHROUGH`.
An example:
@@ -111,26 +113,26 @@ listener:
protocol: UDP
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the listener. | ``string`` | Yes |
|``protocol`` | The protocol of the listener. | ``string`` | Yes |
-{{% /table %}}
+{{}}
### TLS
-The tls field defines TLS configuration for a TransportServer. Please note the current implementation supports TLS termination on multiple ports, where each application owns a dedicated port - the Ingress Controller terminates TLS connections on each port, where each application uses its own cert/key, and routes connections to appropriate application (service) based on that incoming port (any TLS connection regardless of the SNI on a port will be routed to the application that corresponds to that port). An example configuration is shown below:
+The tls field defines TLS configuration for a TransportServer. Please note the current implementation supports TLS termination on multiple ports, where each application owns a dedicated port - NGINX Ingress Controller terminates TLS connections on each port, where each application uses its own cert/key, and routes connections to appropriate application (service) based on that incoming port (any TLS connection regardless of the SNI on a port will be routed to the application that corresponds to that port). An example configuration is shown below:
```yaml
secret: cafe-secret
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``secret`` | The name of a secret with a TLS certificate and key. The secret must belong to the same namespace as the TransportServer. The secret must be of the type ``kubernetes.io/tls`` and contain keys named ``tls.crt`` and ``tls.key`` that contain the certificate and private key as described [here](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls). | ``string`` | No |
-{{% /table %}}
+{{}}
### Upstream
@@ -146,7 +148,7 @@ failTimeout: 30s
loadBalancingMethod: least_conn
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the upstream. Must be a valid DNS label as defined in RFC 1035. For example, ``hello`` and ``upstream-123`` are valid. The name must be unique among all upstreams of the resource. | ``string`` | Yes |
@@ -159,7 +161,7 @@ loadBalancingMethod: least_conn
|``loadBalancingMethod`` | The method used to load balance the upstream servers. By default, connections are distributed between the servers using a weighted round-robin balancing method. See the [upstream](http://nginx.org/en/docs/stream/ngx_stream_upstream_module.html#upstream) section for available methods and their details. | ``string`` | No |
|``backup`` | The name of the backup service of type [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname). This will be used when the primary servers are unavailable. Note: The parameter cannot be used along with the ``random`` , ``hash`` or ``ip_hash`` load balancing methods. | ``string`` | No |
|``backupPort`` | The port of the backup service. The backup port is required if the backup service name is provided. The port must fall into the range ``1..65535``. | ``uint16`` | No |
-{{% /table %}}
+{{}}
### Upstream.Healthcheck
@@ -179,9 +181,9 @@ healthCheck:
port: 8080
```
-Note: This feature is supported only in NGINX Plus.
+{{< note >}} This feature is only supported with NGINX Plus. {{< /note >}}
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``enable`` | Enables a health check for an upstream server. The default is ``false``. | ``boolean`` | No |
@@ -192,7 +194,7 @@ Note: This feature is supported only in NGINX Plus.
|``passes`` | The number of consecutive passed health checks of a particular upstream server after which the server will be considered healthy. The default is ``1``. | ``integer`` | No |
|``port`` | The port used for health check requests. By default, the [server port is used](https://nginx.org/en/docs/stream/ngx_stream_upstream_hc_module.html#health_check_port). Note: in contrast with the port of the upstream, this port is not a service port, but a port of a pod. | ``integer`` | No |
|``match`` | Controls the data to send and the response to expect for the healthcheck. | [match](#upstreamhealthcheckmatch) | No |
-{{% /table %}}
+{{}}
### Upstream.Healthcheck.Match
@@ -208,12 +210,12 @@ Both `send` and `expect` fields can contain hexadecimal literals with the prefix
See the [match](https://nginx.org/en/docs/stream/ngx_stream_upstream_hc_module.html#match) directive for details.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``send`` | A string to send to an upstream server. | ``string`` | No |
-|``expect`` | A literal string or a regular expression that the data obtained from the server should match. The regular expression is specified with the preceding ``~*`` modifier (for case-insensitive matching), or the ``~`` modifier (for case-sensitive matching). The Ingress Controller validates a regular expression using the RE2 syntax. | ``string`` | No |
-{{% /table %}}
+|``expect`` | A literal string or a regular expression that the data obtained from the server should match. The regular expression is specified with the preceding ``~*`` modifier (for case-insensitive matching), or the ``~`` modifier (for case-sensitive matching). NGINX Ingress Controller validates a regular expression using the RE2 syntax. | ``string`` | No |
+{{}}
### UpstreamParameters
@@ -229,7 +231,7 @@ upstreamParameters:
nextUpstreamTries: 1
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``udpRequests`` | The number of datagrams, after receiving which, the next datagram from the same client starts a new session. See the [proxy_requests](https://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_requests) directive. The default is ``0``. | ``int`` | No |
@@ -238,7 +240,7 @@ upstreamParameters:
|``nextUpstream`` | If a connection to the proxied server cannot be established, determines whether a client connection will be passed to the next server. See the [proxy_next_upstream](http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_next_upstream) directive. The default is ``true``. | bool | No |
|``nextUpstreamTries`` | The number of tries for passing a connection to the next server. See the [proxy_next_upstream_tries](http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_next_upstream_tries) directive. The default is ``0``. | ``int`` | No |
|``nextUpstreamTimeout`` | The time allowed to pass a connection to the next server. See the [proxy_next_upstream_timeout](http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_next_upstream_timeout) directive. The default us ``0``. | ``string`` | No |
-{{% /table %}}
+{{}}
### SessionParameters
@@ -249,11 +251,11 @@ sessionParameters:
timeout: 50s
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``timeout`` | The timeout between two successive read or write operations on client or proxied server connections. See [proxy_timeout](http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html#proxy_timeout) directive. The default is ``10m``. | ``string`` | No |
-{{% /table %}}
+{{}}
### Action
@@ -266,11 +268,11 @@ action:
pass: dns-app
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``pass`` | Passes connections/datagrams to an upstream. The upstream with that name must be defined in the resource. | ``string`` | Yes |
-{{% /table %}}
+{{}}
## Using TransportServer
@@ -280,7 +282,8 @@ For example, the following command creates a TransportServer resource defined in
```shell
kubectl apply -f transport-server-passthrough.yaml
-
+```
+```text
transportserver.k8s.nginx.org/secure-app created
```
@@ -288,7 +291,8 @@ You can get the resource by running:
```shell
kubectl get transportserver secure-app
-
+```
+```text
NAME AGE
secure-app 46sm
```
@@ -332,28 +336,16 @@ spec:
port: 80
```
-Snippets are intended to be used by advanced NGINX users who need more control over the generated NGINX configuration.
-
-However, because of the disadvantages described below, snippets are disabled by default. To use snippets, set the [`enable-snippets`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-enable-snippets) command-line argument.
-
-Disadvantages of using snippets:
-
-- *Complexity*. To use snippets, you will need to:
- - Understand NGINX configuration primitives and implement a correct NGINX configuration.
- - Understand how the IC generates NGINX configuration so that a snippet doesn't interfere with the other features in the configuration.
-- *Decreased robustness*. An incorrect snippet makes the NGINX config invalid which will lead to a failed reload. This will prevent any new configuration updates, including updates for the other TransportServer resource until the snippet is fixed.
-- *Security implications*. Snippets give access to NGINX configuration primitives and those primitives are not validated by the Ingress Controller.
-
-> Note: during a period when the NGINX config includes an invalid snippet, NGINX will continue to operate with the latest valid configuration.
+{{< note >}} To configure snippets in the `stream` context, use `stream-snippets` ConfigMap key. {{< /note >}}
-> Note: to configure snippets in the `stream` context, use `stream-snippets` ConfigMap key.
+For additional information, view the [Advanced configuration with Snippets]({{< relref "configuration/ingress-resources/advanced-configuration-with-snippets.md" >}}) topic.
### Validation
Two types of validation are available for the TransportServer resource:
- *Structural validation* by the `kubectl` and Kubernetes API server.
-- *Comprehensive validation* by the Ingress Controller.
+- *Comprehensive validation* by NGINX Ingress Controller.
#### Structural Validation
@@ -365,31 +357,34 @@ If you try to create (or update) a resource that violates the structural schema
```shell
kubectl apply -f transport-server-passthrough.yaml
-
- error: error validating "transport-server-passthrough.yaml": error validating data: ValidationError(TransportServer.spec.upstreams[0].port): invalid type for org.nginx.k8s.v1.TransportServer.spec.upstreams.port: got "string", expected "integer"; if you choose to ignore these errors, turn validation off with --validate=false
+ ```
+ ```text
+ error: error validating "transport-server-passthrough.yaml": error validating data: ValidationError(TransportServer.spec.upstreams[0].port): invalid type for org.nginx.k8s.v1.TransportServer.spec.upstreams.port: got "string", expected "integer"; if you choose to ignore these errors, turn validation off with --validate=false
```
- Example of Kubernetes API server validation:
```shell
kubectl apply -f transport-server-passthrough.yaml --validate=false
-
- The TransportServer "secure-app" is invalid: []: Invalid value: map[string]interface {}{ ... }: validation failure list:
- spec.upstreams.port in body must be of type integer: "string"
+ ```
+ ```text
+ The TransportServer "secure-app" is invalid: []: Invalid value: map[string]interface {}{ ... }: validation failure list:
+ spec.upstreams.port in body must be of type integer: "string"
```
-If a resource is not rejected (it doesn't violate the structural schema), the Ingress Controller will validate it further.
+If a resource is not rejected (it doesn't violate the structural schema), NGINX Ingress Controller will validate it further.
#### Comprehensive Validation
-The Ingress Controller validates the fields of a TransportServer resource. If a resource is invalid, the Ingress Controller will reject it: the resource will continue to exist in the cluster, but the Ingress Controller will ignore it.
+NGINX Ingress Controller validates the fields of a TransportServer resource. If a resource is invalid, NGINX Ingress Controller will reject it: the resource will continue to exist in the cluster, but NGINX Ingress Controller will ignore it.
-You can check if the Ingress Controller successfully applied the configuration for a TransportServer. For our example `secure-app` TransportServer, we can run:
+You can check if NGINX Ingress Controller successfully applied the configuration for a TransportServer. For our example `secure-app` TransportServer, we can run:
```shell
kubectl describe ts secure-app
-
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
@@ -398,12 +393,13 @@ Events:
Note how the events section includes a Normal event with the AddedOrUpdated reason that informs us that the configuration was successfully applied.
-If you create an invalid resource, the Ingress Controller will reject it and emit a Rejected event. For example, if you create a TransportServer `secure-app` with a pass action that references a non-existing upstream, you will get :
+If you create an invalid resource, NGINX Ingress Controller will reject it and emit a Rejected event. For example, if you create a TransportServer `secure-app` with a pass action that references a non-existing upstream, you will get :
```shell
kubectl describe ts secure-app
-
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
@@ -412,8 +408,8 @@ Events:
Note how the events section includes a Warning event with the Rejected reason.
-**Note**: If you make an existing resource invalid, the Ingress Controller will reject it and remove the corresponding configuration from NGINX.
+**Note**: If you make an existing resource invalid, NGINX Ingress Controller will reject it and remove the corresponding configuration from NGINX.
## Customization via ConfigMap
-The [ConfigMap](/nginx-ingress-controller/configuration/global-configuration/configmap-resource) keys (except for `stream-snippets`, `stream-log-format`, `resolver-addresses`, `resolver-ipv6`, `resolver-valid` and `resolver-timeout`) do not affect TransportServer resources.
+The [ConfigMap]({{< relref "configuration/global-configuration/configmap-resource.md" >}}) keys (except for `stream-snippets`, `stream-log-format`, `resolver-addresses`, `resolver-ipv6`, `resolver-valid` and `resolver-timeout`) do not affect TransportServer resources.
diff --git a/docs/content/configuration/virtualserver-and-virtualserverroute-resources.md b/docs/content/configuration/virtualserver-and-virtualserverroute-resources.md
index bf74e6e4e7..10de579463 100644
--- a/docs/content/configuration/virtualserver-and-virtualserverroute-resources.md
+++ b/docs/content/configuration/virtualserver-and-virtualserverroute-resources.md
@@ -2,18 +2,22 @@
docs: DOCS-599
doctypes:
- ''
-title: VirtualServer and VirtualServerRoute Resources
+title: VirtualServer and VirtualServerRoute resources
toc: true
weight: 1600
---
+This document is reference material for the VirtualServer and VirtualServerRoute resources used by F5 NGINX Ingress Controller.
+
VirtualServer and VirtualServerRoute resources are load balancing configurations recommended as an alternative to the Ingress resource.
They enable use cases not supported with the Ingress resource, such as traffic splitting and advanced content-based routing. The resources are implemented as [Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/).
-This document is the reference documentation for the resources. To see additional examples of using the resources for specific use cases, go to the [examples/custom-resources](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/custom-resources) folder in our GitHub repo.
+The GitHub repository has [examples of the resources](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/custom-resources) for specific use cases.
+
+---
-## VirtualServer Specification
+## VirtualServer specification
The VirtualServer resource defines load balancing configuration for a domain name, such as `example.com`. Below is an example of such configuration:
@@ -52,7 +56,7 @@ spec:
pass: tea
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``host`` | The host (domain name) of the server. Must be a valid subdomain as defined in RFC 1123, such as ``my-app`` or ``hello.example.com``. When using a wildcard domain like ``*.example.com`` the domain must be contained in double quotes. The ``host`` value needs to be unique among all Ingress and VirtualServer resources. See also [Handling Host and Listener Collisions](/nginx-ingress-controller/configuration/handling-host-and-listener-collisions). | ``string`` | Yes |
@@ -68,7 +72,7 @@ spec:
|``internalRoute`` | Specifies if the VirtualServer resource is an internal route or not. | ``boolean`` | No |
|``http-snippets`` | Sets a custom snippet in the http context. | ``string`` | No |
|``server-snippets`` | Sets a custom snippet in server context. Overrides the ``server-snippets`` ConfigMap key. | ``string`` | No |
-{{% /table %}}
+{{}}
### VirtualServer.TLS
@@ -80,13 +84,13 @@ redirect:
enable: true
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``secret`` | The name of a secret with a TLS certificate and key. The secret must belong to the same namespace as the VirtualServer. The secret must be of the type ``kubernetes.io/tls`` and contain keys named ``tls.crt`` and ``tls.key`` that contain the certificate and private key as described [here](https://kubernetes.io/docs/concepts/services-networking/ingress/#tls). If the secret doesn't exist or is invalid, NGINX will break any attempt to establish a TLS connection to the host of the VirtualServer. If the secret is not specified but [wildcard TLS secret](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-wildcard-tls-secret) is configured, NGINX will use the wildcard secret for TLS termination. | ``string`` | No |
|``redirect`` | The redirect configuration of the TLS for a VirtualServer. | [tls.redirect](#virtualservertlsredirect) | No | ### VirtualServer.TLS.Redirect |
|``cert-manager`` | The cert-manager configuration of the TLS for a VirtualServer. | [tls.cert-manager](#virtualservertlscertmanager) | No | ### VirtualServer.TLS.CertManager |
-{{% /table %}}
+{{}}
### VirtualServer.TLS.Redirect
@@ -98,13 +102,13 @@ code: 301
basedOn: scheme
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``enable`` | Enables a TLS redirect for a VirtualServer. The default is ``False``. | ``boolean`` | No |
|``code`` | The status code of a redirect. The allowed values are: ``301`` , ``302`` , ``307`` , ``308``. The default is ``301``. | ``int`` | No |
|``basedOn`` | The attribute of a request that NGINX will evaluate to send a redirect. The allowed values are ``scheme`` (the scheme of the request) or ``x-forwarded-proto`` (the ``X-Forwarded-Proto`` header of the request). The default is ``scheme``. | ``string`` | No | ### VirtualServer.Policy |
-{{% /table %}}
+{{}}
### VirtualServer.TLS.CertManager
@@ -115,7 +119,7 @@ cert-manager:
cluster-issuer: "my-issuer-name"
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``issuer`` | the name of an Issuer. An Issuer is a cert-manager resource which describes the certificate authority capable of signing certificates. The Issuer must be in the same namespace as the VirtualServer resource. Please note that one of `issuer` and `cluster-issuer` are required, but they are mutually exclusive - one and only one must be defined. | ``string`` | No |
@@ -127,7 +131,7 @@ cert-manager:
|``renew-before`` | this annotation allows you to configure spec.renewBefore field for the Certificate to be generated. Must be specified using a [Go time.Duration](https://pkg.go.dev/time#ParseDuration) string format, which does not allow the d (days) suffix. You must specify these values using s, m, and h suffixes instead. | ``string`` | No |
|``usages`` | This field allows you to configure spec.usages field for the Certificate to be generated. Pass a string with comma-separated values i.e. ``key agreement,digital signature, server auth``. An exhaustive list of supported key usages can be found in the [the cert-manager api documentation](https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.KeyUsage). | ``string`` | No |
|``issue-temp-cert`` | When ``true``, ask cert-manager for a [temporary self-signed certificate](https://cert-manager.io/docs/usage/certificate/#temporary-certificates-while-issuing) pending the issuance of the Certificate. This allows HTTPS-only servers to use ACME HTTP01 challenges when the TLS secret does not exist yet. | ``boolean`` | No |
-{{% /table %}}
+{{}}
### VirtualServer.Listener
The listener field defines a custom HTTP and/or HTTPS listener.
@@ -138,12 +142,12 @@ http: http-8083
https: https-8443
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``http`` | The name of am HTTP listener defined in a [GlobalConfiguration](/nginx-ingress-controller/configuration/global-configuration/globalconfiguration-resource/) resource. | ``string`` | No |
|``https`` | The name of an HTTPS listener defined in a [GlobalConfiguration](/nginx-ingress-controller/configuration/global-configuration/globalconfiguration-resource/) resource. | ``string`` | No |
-{{% /table %}}
+{{}}
### VirtualServer.ExternalDNS
@@ -153,7 +157,7 @@ The externalDNS field configures controlling DNS records dynamically for Virtual
enable: true
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``enable`` | Enables ExternalDNS integration for a VirtualServer resource. The default is ``false``. | ``string`` | No |
@@ -161,7 +165,7 @@ enable: true
|``providerSpecific`` | Configure provider specific properties which holds the name and value of a configuration which is specific to individual DNS providers. | [[]ProviderSpecific](#virtualserverexternaldnsproviderspecific) | No |
|``recordTTL`` | TTL for the DNS record. This defaults to 0 if not defined. See [the ExternalDNS TTL documentation for provider-specific defaults](https://kubernetes-sigs.github.io/external-dns/v0.12.0/ttl/#providers) | ``int64`` | No |
|``recordType`` | The record Type that should be created, e.g. "A", "AAAA", "CNAME". This is automatically computed based on the external endpoints if not defined. | ``string`` | No |
-{{% /table %}}
+{{}}
### VirtualServer.ExternalDNS.ProviderSpecific
@@ -174,12 +178,12 @@ The providerSpecific field of the externalDNS block allows the specification of
value: my-value2
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the key value pair. | ``string`` | Yes |
|``value`` | The value of the key value pair. | ``string`` | Yes |
-{{% /table %}}
+{{}}
### VirtualServer.Policy
@@ -189,12 +193,12 @@ The policy field references a [Policy resource](/nginx-ingress-controller/config
name: access-control
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of a policy. If the policy doesn't exist or invalid, NGINX will respond with an error response with the `500` status code. | ``string`` | Yes |
|``namespace`` | The namespace of a policy. If not specified, the namespace of the VirtualServer resource is used. | ``string`` | No |
-{{% /table %}}
+{{}}
### VirtualServer.Route
@@ -206,7 +210,7 @@ The route defines rules for matching client requests to actions like passing a r
pass: tea
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``path`` | The path of the route. NGINX will match it against the URI of a request. Possible values are: a prefix ( ``/`` , ``/path`` ), an exact match ( ``=/exact/match`` ), a case insensitive regular expression ( ``~*^/Bar.*\.jpg`` ) or a case sensitive regular expression ( ``~^/foo.*\.jpg`` ). In the case of a prefix (must start with ``/`` ) or an exact match (must start with ``=`` ), the path must not include any whitespace characters, ``{`` , ``}`` or ``;``. In the case of the regex matches, all double quotes ``"`` must be escaped and the match can't end in an unescaped backslash ``\``. The path must be unique among the paths of all routes of the VirtualServer. Check the [location](https://nginx.org/en/docs/http/ngx_http_core_module.html#location) directive for more information. | ``string`` | Yes |
@@ -218,11 +222,11 @@ The route defines rules for matching client requests to actions like passing a r
|``route`` | The name of a VirtualServerRoute resource that defines this route. If the VirtualServerRoute belongs to a different namespace than the VirtualServer, you need to include the namespace. For example, ``tea-namespace/tea``. | ``string`` | No |
|``errorPages`` | The custom responses for error codes. NGINX will use those responses instead of returning the error responses from the upstream servers or the default responses generated by NGINX. A custom response can be a redirect or a canned response. For example, a redirect to another URL if an upstream server responded with a 404 status code. | [[]errorPage](#errorpage) | No |
|``location-snippets`` | Sets a custom snippet in the location context. Overrides the ``location-snippets`` ConfigMap key. | ``string`` | No |
-{{% /table %}}
+{{}}
\* -- a route must include exactly one of the following: `action`, `splits`, or `route`.
-## VirtualServerRoute Specification
+## VirtualServerRoute specification
The VirtualServerRoute resource defines a route for a VirtualServer. It can consist of one or multiple subroutes. The VirtualServerRoute is an alternative to [Mergeable Ingress types](/nginx-ingress-controller/configuration/ingress-resources/cross-namespace-configuration).
@@ -278,14 +282,14 @@ spec:
Note that each subroute must have a `path` that starts with the same prefix (here `/coffee`), which is defined in the route of the VirtualServer. Additionally, the `host` in the VirtualServerRoute must be the same as the `host` of the VirtualServer.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``host`` | The host (domain name) of the server. Must be a valid subdomain as defined in RFC 1123, such as ``my-app`` or ``hello.example.com``. When using a wildcard domain like ``*.example.com`` the domain must be contained in double quotes. Must be the same as the ``host`` of the VirtualServer that references this resource. | ``string`` | Yes |
|``upstreams`` | A list of upstreams. | [[]upstream](#upstream) | No |
|``subroutes`` | A list of subroutes. | [[]subroute](#virtualserverroutesubroute) | No |
|``ingressClassName`` | Specifies which Ingress Controller must handle the VirtualServerRoute resource. Must be the same as the ``ingressClassName`` of the VirtualServer that references this resource. | ``string``_ | No |
-{{% /table %}}
+{{}}
### VirtualServerRoute.Subroute
@@ -297,7 +301,7 @@ action:
pass: coffee
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``path`` | The path of the subroute. NGINX will match it against the URI of a request. Possible values are: a prefix ( ``/`` , ``/path`` ), an exact match ( ``=/exact/match`` ), a case insensitive regular expression ( ``~*^/Bar.*\.jpg`` ) or a case sensitive regular expression ( ``~^/foo.*\.jpg`` ). In the case of a prefix, the path must start with the same path as the path of the route of the VirtualServer that references this resource. In the case of an exact or regex match, the path must be the same as the path of the route of the VirtualServer that references this resource. A matching path of the route of the VirtualServer but in different type is not accepted, e.g. a regex path (`~/match`) cannot be used with a prefix path in VirtualServer (`/match`) In the case of a prefix or an exact match, the path must not include any whitespace characters, ``{`` , ``}`` or ``;``. In the case of the regex matches, all double quotes ``"`` must be escaped and the match can't end in an unescaped backslash ``\``. The path must be unique among the paths of all subroutes of the VirtualServerRoute. | ``string`` | Yes |
@@ -308,11 +312,11 @@ action:
|``matches`` | The matching rules for advanced content-based routing. Requires the default ``action`` or ``splits``. Unmatched requests will be handled by the default ``action`` or ``splits``. | [matches](#match) | No |
|``errorPages`` | The custom responses for error codes. NGINX will use those responses instead of returning the error responses from the upstream servers or the default responses generated by NGINX. A custom response can be a redirect or a canned response. For example, a redirect to another URL if an upstream server responded with a 404 status code. | [[]errorPage](#errorpage) | No |
|``location-snippets`` | Sets a custom snippet in the location context. Overrides the ``location-snippets`` of the VirtualServer (if set) or the ``location-snippets`` ConfigMap key. | ``string`` | No |
-{{% /table %}}
+{{}}
\* -- a subroute must include exactly one of the following: `action` or `splits`.
-## Common Parts of the VirtualServer and VirtualServerRoute
+## Common VirtualServer and VirtualServerRoute specifications
### Upstream
@@ -342,12 +346,12 @@ tls:
**Note**: The WebSocket protocol is supported without any additional configuration.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the upstream. Must be a valid DNS label as defined in RFC 1035. For example, ``hello`` and ``upstream-123`` are valid. The name must be unique among all upstreams of the resource. | ``string`` | Yes |
|``service`` | The name of a [service](https://kubernetes.io/docs/concepts/services-networking/service/). The service must belong to the same namespace as the resource. If the service doesn't exist, NGINX will assume the service has zero endpoints and return a ``502`` response for requests for this upstream. For NGINX Plus only, services of type [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) are also supported (check the [prerequisites](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/ingress-resources/externalname-services#prerequisites) ). | ``string`` | Yes |
-|``subselector`` | Selects the pods within the service using label keys and values. By default, all pods of the service are selected. Note: the specified labels are expected to be present in the pods when they are created. If the pod labels are updated, the Ingress Controller will not see that change until the number of the pods is changed. | ``map[string]string`` | No |
+|``subselector`` | Selects the pods within the service using label keys and values. By default, all pods of the service are selected. Note: the specified labels are expected to be present in the pods when they are created. If the pod labels are updated, NGINX Ingress Controller will not see that change until the number of the pods is changed. | ``map[string]string`` | No |
|``use-cluster-ip`` | Enables using the Cluster IP and port of the service instead of the default behavior of using the IP and port of the pods. When this field is enabled, the fields that configure NGINX behavior related to multiple upstream servers (like ``lb-method`` and ``next-upstream``) will have no effect, as NGINX Ingress Controller will configure NGINX with only one upstream server that will match the service Cluster IP. | ``boolean`` | No |
|``port`` | The port of the service. If the service doesn't define that port, NGINX will assume the service has zero endpoints and return a ``502`` response for requests for this upstream. The port must fall into the range ``1..65535``. | ``uint16`` | Yes |
|``lb-method`` | The load [balancing method](https://docs.nginx.com/nginx/admin-guide/load-balancer/http-load-balancer/#choosing-a-load-balancing-method). To use the round-robin method, specify ``round_robin``. The default is specified in the ``lb-method`` ConfigMap key. | ``string`` | No |
@@ -373,7 +377,7 @@ tls:
|``type`` |The type of the upstream. Supported values are ``http`` and ``grpc``. The default is ``http``. For gRPC, it is necessary to enable HTTP/2 in the [ConfigMap](/nginx-ingress-controller/configuration/global-configuration/configmap-resource/#listeners) and configure TLS termination in the VirtualServer. | ``string`` | No |
|``backup`` | The name of the backup service of type [ExternalName](https://kubernetes.io/docs/concepts/services-networking/service/#externalname). This will be used when the primary servers are unavailable. Note: The parameter cannot be used along with the ``random`` , ``hash`` or ``ip_hash`` load balancing methods. | ``string`` | No |
|``backupPort`` | The port of the backup service. The backup port is required if the backup service name is provided. The port must fall into the range ``1..65535``. | ``uint16`` | No |
-{{% /table %}}
+{{}}
### Upstream.Buffers
@@ -386,20 +390,20 @@ size: 8K
See the [proxy_buffers](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffers) directive for additional information.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``number`` | Configures the number of buffers. The default is set in the ``proxy-buffers`` ConfigMap key. | ``int`` | Yes |
|``size`` | Configures the size of a buffer. The default is set in the ``proxy-buffers`` ConfigMap key. | ``string`` | Yes |
-{{% /table %}}
+{{}}
### Upstream.TLS
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``enable`` | Enables HTTPS for requests to upstream servers. The default is ``False`` , meaning that HTTP will be used. Note: by default, NGINX will not verify the upstream server certificate. To enable the verification, configure an [EgressMTLS Policy](/nginx-ingress-controller/configuration/policy-resource/#egressmtls). | ``boolean`` | No |
-{{% /table %}}
+{{}}
### Upstream.Queue
@@ -414,12 +418,12 @@ See [`queue`](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#queue
Note: This feature is supported only in NGINX Plus.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``size`` | The size of the queue. | ``int`` | Yes |
|``timeout`` | The timeout of the queue. A request cannot be queued for a period longer than the timeout. The default is ``60s``. | ``string`` | No |
-{{% /table %}}
+{{}}
### Upstream.Healthcheck
@@ -454,7 +458,7 @@ healthCheck:
Note: This feature is supported only in NGINX Plus.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``enable`` | Enables a health check for an upstream server. The default is ``false``. | ``boolean`` | No |
@@ -475,7 +479,7 @@ Note: This feature is supported only in NGINX Plus.
|``mandatory`` | Require every newly added server to pass all configured health checks before NGINX Plus sends traffic to it. If this is not specified, or is set to false, the server will be initially considered healthy. When combined with [slow-start](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#slow_start), it gives a new server more time to connect to databases and “warm up” before being asked to handle their full share of traffic. | ``bool`` | No |
|``persistent`` | Set the initial “up” state for a server after reload if the server was considered healthy before reload. Enabling persistent requires that the mandatory parameter is also set to `true`. | ``bool`` | No |
|``keepalive-time`` | Enables [keepalive](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) connections for health checks and specifies the time during which requests can be processed through one keepalive connection. The default is ``60s``. | ``string`` | No |
-{{% /table %}}
+{{}}
### Upstream.SessionCookie
@@ -502,7 +506,7 @@ See the [`sticky`](https://nginx.org/en/docs/http/ngx_http_upstream_module.html?
Note: This feature is supported only in NGINX Plus.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``enable`` | Enables session persistence with a session cookie for an upstream server. The default is ``false``. | ``boolean`` | No |
@@ -513,7 +517,7 @@ Note: This feature is supported only in NGINX Plus.
|``httpOnly`` | Adds the ``HttpOnly`` attribute to the cookie. | ``boolean`` | No |
|``secure`` | Adds the ``Secure`` attribute to the cookie. | ``boolean`` | No |
|``samesite`` | Adds the ``SameSite`` attribute to the cookie. The allowed values are: ``strict``, ``lax``, ``none`` | ``string`` | No |
-{{% /table %}}
+{{}}
### Header
@@ -524,12 +528,12 @@ name: Host
value: example.com
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the header. | ``string`` | Yes |
|``value`` | The value of the header. | ``string`` | No |
-{{% /table %}}
+{{}}
### Action
@@ -543,14 +547,14 @@ In the example below, client requests are passed to an upstream `coffee`:
pass: coffee
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``pass`` | Passes requests to an upstream. The upstream with that name must be defined in the resource. | ``string`` | No |
|``redirect`` | Redirects requests to a provided URL. | [action.redirect](#actionredirect) | No |
|``return`` | Returns a preconfigured response. | [action.return](#actionreturn) | No |
|``proxy`` | Passes requests to an upstream with the ability to modify the request/response (for example, rewrite the URI or modify the headers). | [action.proxy](#actionproxy) | No |
-{{% /table %}}
+{{}}
\* -- an action must include exactly one of the following: `pass`, `redirect`, `return` or `proxy`.
@@ -566,12 +570,12 @@ redirect:
code: 301
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``url`` | The URL to redirect the request to. Supported NGINX variables: ``$scheme`` , ``$http_x_forwarded_proto`` , ``$request_uri`` , ``$host``. Variables must be enclosed in curly braces. For example: ``${host}${request_uri}``. | ``string`` | Yes |
|``code`` | The status code of a redirect. The allowed values are: ``301`` , ``302`` , ``307`` , ``308``. The default is ``301``. | ``int`` | No |
-{{% /table %}}
+{{}}
### Action.Return
@@ -589,14 +593,14 @@ return:
value: espresso
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``code`` | The status code of the response. The allowed values are: ``2XX``, ``4XX`` or ``5XX``. The default is ``200``. | ``int`` | No |
|``type`` | The MIME type of the response. The default is ``text/plain``. | ``string`` | No |
|``body`` | The body of the response. Supports NGINX variables*. Variables must be enclosed in curly brackets. For example: ``Request is ${request_uri}\n``. | ``string`` | Yes |
|``headers`` | The custom headers of the response. | [[]Action.Return.Header](#actionreturnheader) | No |
-{{% /table %}}
+{{}}
\* -- Supported NGINX variables: `$request_uri`, `$request_method`, `$request_body`, `$scheme`, `$http_`, `$args`, `$arg_`, `$cookie_`, `$host`, `$request_time`, `$request_length`, `$nginx_version`, `$pid`, `$connection`, `$remote_addr`, `$remote_port`, `$time_iso8601`, `$time_local`, `$server_addr`, `$server_port`, `$server_name`, `$server_protocol`, `$connections_active`, `$connections_reading`, `$connections_writing` and `$connections_waiting`.
@@ -609,12 +613,12 @@ name: x-coffee
value: espresso
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the header. | ``string`` | Yes |
|``value`` | The value of the header. | ``string`` | Yes |
-{{% /table %}}
+{{}}
### Action.Proxy
@@ -649,25 +653,25 @@ proxy:
rewritePath: /
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``upstream`` | The name of the upstream which the requests will be proxied to. The upstream with that name must be defined in the resource. | ``string`` | Yes |
|``requestHeaders`` | The request headers modifications. | [action.Proxy.RequestHeaders](#actionproxyrequestheaders) | No |
|``responseHeaders`` | The response headers modifications. | [action.Proxy.ResponseHeaders](#actionproxyresponseheaders) | No |
|``rewritePath`` | The rewritten URI. If the route path is a regular expression -- starts with `~` -- the `rewritePath` can include capture groups with ``$1-9``. For example `$1` for the first group, and so on. For more information, check the [rewrite](https://github.com/nginxinc/kubernetes-ingress/tree/v3.5.2/examples/custom-resources/rewrites) example. | ``string`` | No |
-{{% /table %}}
+{{}}
### Action.Proxy.RequestHeaders
The RequestHeaders field modifies the headers of the request to the proxied upstream server.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``pass`` | Passes the original request headers to the proxied upstream server. See the [proxy_pass_request_header](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_request_headers) directive for more information. Default is true. | ``bool`` | No |
|``set`` | Allows redefining or appending fields to present request headers passed to the proxied upstream servers. See the [proxy_set_header](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header) directive for more information. | [[]header](#actionproxyrequestheaderssetheader) | No |
-{{% /table %}}
+{{}}
### Action.Proxy.RequestHeaders.Set.Header
@@ -678,19 +682,19 @@ name: My-Header
value: My-Value
```
-It is possible to override the default value of the `Host` header, which the Ingress Controller sets to [`$host`](https://nginx.org/en/docs/http/ngx_http_core_module.html#var_host):
+It is possible to override the default value of the `Host` header, which NGINX Ingress Controller sets to [`$host`](https://nginx.org/en/docs/http/ngx_http_core_module.html#var_host):
```yaml
name: Host
value: example.com
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the header. | ``string`` | Yes |
|``value`` | The value of the header. Supports NGINX variables*. Variables must be enclosed in curly brackets. For example: ``${scheme}``. | ``string`` | No |
-{{% /table %}}
+{{}}
\* -- Supported NGINX variables: `$request_uri`, `$request_method`, `$request_body`, `$scheme`, `$http_`, `$args`, `$arg_`, `$cookie_`, `$host`, `$request_time`, `$request_length`, `$nginx_version`, `$pid`, `$connection`, `$remote_addr`, `$remote_port`, `$time_iso8601`, `$time_local`, `$server_addr`, `$server_port`, `$server_name`, `$server_protocol`, `$connections_active`, `$connections_reading`, `$connections_writing`, `$connections_waiting`, `$ssl_cipher`, `$ssl_ciphers`, `$ssl_client_cert`, `$ssl_client_escaped_cert`, `$ssl_client_fingerprint`, `$ssl_client_i_dn`, `$ssl_client_i_dn_legacy`, `$ssl_client_raw_cert`, `$ssl_client_s_dn`, `$ssl_client_s_dn_legacy`, `$ssl_client_serial`, `$ssl_client_v_end`, `$ssl_client_v_remain`, `$ssl_client_v_start`, `$ssl_client_verify`, `$ssl_curves`, `$ssl_early_data`, `$ssl_protocol`, `$ssl_server_name`, `$ssl_session_id`, `$ssl_session_reused`, `$jwt_claim_` (NGINX Plus only) and `$jwt_header_` (NGINX Plus only).
@@ -698,14 +702,14 @@ value: example.com
The ResponseHeaders field modifies the headers of the response to the client.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``hide`` | The headers that will not be passed* in the response to the client from a proxied upstream server. See the [proxy_hide_header](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_hide_header) directive for more information. | ``[]string`` | No |
|``pass`` | Allows passing the hidden header fields* to the client from a proxied upstream server. See the [proxy_pass_header](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_pass_header) directive for more information. | ``[]string`` | No |
|``ignore`` | Disables processing of certain headers** to the client from a proxied upstream server. See the [proxy_ignore_headers](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers) directive for more information. | ``[]string`` | No |
|``add`` | Adds headers to the response to the client. | [[]addHeader](#addheader) | No |
-{{% /table %}}
+{{}}
\* -- Default hidden headers are: `Date`, `Server`, `X-Pad` and `X-Accel-...`.
@@ -721,17 +725,17 @@ value: My-Value
always: true
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the header. | ``string`` | Yes |
|``value`` | The value of the header. Supports NGINX variables*. Variables must be enclosed in curly brackets. For example: ``${scheme}``. | ``string`` | No |
|``always`` | If set to true, add the header regardless of the response status code**. Default is false. See the [add_header](http://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header) directive for more information. | ``bool`` | No |
-{{% /table %}}
+{{}}
\* -- Supported NGINX variables: `$request_uri`, `$request_method`, `$request_body`, `$scheme`, `$http_`, `$args`, `$arg_`, `$cookie_`, `$host`, `$request_time`, `$request_length`, `$nginx_version`, `$pid`, `$connection`, `$remote_addr`, `$remote_port`, `$time_iso8601`, `$time_local`, `$server_addr`, `$server_port`, `$server_name`, `$server_protocol`, `$connections_active`, `$connections_reading`, `$connections_writing`, `$connections_waiting`, `$ssl_cipher`, `$ssl_ciphers`, `$ssl_client_cert`, `$ssl_client_escaped_cert`, `$ssl_client_fingerprint`, `$ssl_client_i_dn`, `$ssl_client_i_dn_legacy`, `$ssl_client_raw_cert`, `$ssl_client_s_dn`, `$ssl_client_s_dn_legacy`, `$ssl_client_serial`, `$ssl_client_v_end`, `$ssl_client_v_remain`, `$ssl_client_v_start`, `$ssl_client_verify`, `$ssl_curves`, `$ssl_early_data`, `$ssl_protocol`, `$ssl_server_name`, `$ssl_session_id`, `$ssl_session_reused`, `$jwt_claim_` (NGINX Plus only) and `$jwt_header_` (NGINX Plus only).
-\*\* -- If `always` is false, the response header is added only if the response status code is any of `200`, `201`, `204`, `206`, `301`, `302`, `303`, `304`, `307` or `308`.
+{{< note >}} If `always` is false, the response header is added only if the response status code is any of `200`, `201`, `204`, `206`, `301`, `302`, `303`, `304`, `307` or `308`. {{< /note >}}
### Split
@@ -749,12 +753,12 @@ splits:
pass: coffee-v2
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``weight`` | The weight of an action. Must fall into the range ``0..100``. The sum of the weights of all splits must be equal to ``100``. | ``int`` | Yes |
|``action`` | The action to perform for a request. | [action](#action) | Yes |
-{{% /table %}}
+{{}}
### Match
@@ -800,21 +804,21 @@ action:
pass: coffee
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``conditions`` | A list of conditions. Must include at least 1 condition. | [[]condition](#condition) | Yes |
|``action`` | The action to perform for a request. | [action](#action) | No |
|``splits`` | The splits configuration for traffic splitting. Must include at least 2 splits. | [[]split](#split) | No |
-{{% /table %}}
+{{}}
-\* -- a match must include exactly one of the following: `action` or `splits`.
+{{< note >}} A match must include exactly one of the following: `action` or `splits`. {{< /note >}}
### Condition
The condition defines a condition in a match.
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``header`` | The name of a header. Must consist of alphanumeric characters or ``-``. | ``string`` | No |
@@ -822,9 +826,9 @@ The condition defines a condition in a match.
|``argument`` | The name of an argument. Must consist of alphanumeric characters or ``_``. | ``string`` | No |
|``variable`` | The name of an NGINX variable. Must start with ``$``. See the list of the supported variables below the table. | ``string`` | No |
|``value`` | The value to match the condition against. How to define a value is shown below the table. | ``string`` | Yes |
-{{% /table %}}
+{{}}
-\* -- a condition must include exactly one of the following: `header`, `cookie`, `argument` or `variable`.
+{{< note >}} a condition must include exactly one of the following: `header`, `cookie`, `argument` or `variable`. {{< /note >}}
Supported NGINX variables: `$args`, `$http2`, `$https`, `$remote_addr`, `$remote_port`, `$query_string`, `$request`, `$request_body`, `$request_uri`, `$request_method`, `$scheme`. Find the documentation for each variable [here](https://nginx.org/en/docs/varindex.html).
@@ -838,7 +842,7 @@ The value supports two kinds of matching:
- `!~^yes` -- negation of the previous regular expression that succeeds for strings like `YES`, `Yes123`, `noyes`. (The negation mechanism is not part of the PCRE syntax).
- `~*no$` -- a case-insensitive regular expression that matches any string that ends with `no`. For example: `no`, `123no`, `123NO`.
-**Note**: a value must not include any unescaped double quotes (`"`) and must not end with an unescaped backslash (`\`). For example, the following are invalid values: `some"value`, `somevalue\`.
+{{< note >}} A value must not include any unescaped double quotes (`"`) and must not end with an unescaped backslash (`\`). For example, the following are invalid values: `some"value`, `somevalue\`. {{< /note >}}
### ErrorPage
@@ -857,15 +861,15 @@ errorPages:
body: "Original resource not found, but success!"
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``codes`` | A list of error status codes. | ``[]int`` | Yes |
|``redirect`` | The redirect action for the given status codes. | [errorPage.Redirect](#errorpageredirect) | No |
|``return`` | The canned response action for the given status codes. | [errorPage.Return](#errorpagereturn) | No |
-{{% /table %}}
+{{}}
-\* -- an errorPage must include exactly one of the following: `return` or `redirect`.
+{{< note >}} An errorPage must include exactly one of the following: `return` or `redirect`. {{< /note >}}
### ErrorPage.Redirect
@@ -880,12 +884,12 @@ redirect:
url: ${scheme}://cafe.example.com/error.html
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``code`` | The status code of a redirect. The allowed values are: ``301`` , ``302`` , ``307`` , ``308``. The default is ``301``. | ``int`` | No |
|``url`` | The URL to redirect the request to. Supported NGINX variables: ``$scheme`` and ``$http_x_forwarded_proto``. Variables must be enclosed in curly braces. For example: ``${scheme}``. | ``string`` | Yes |
-{{% /table %}}
+{{}}
### ErrorPage.Return
@@ -905,14 +909,14 @@ return:
value: ${upstream_status}
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``code`` | The status code of the response. The default is the status code of the original response. | ``int`` | No |
|``type`` | The MIME type of the response. The default is ``text/html``. | ``string`` | No |
|``body`` | The body of the response. Supported NGINX variable: ``$upstream_status`` . Variables must be enclosed in curly braces. For example: ``${upstream_status}``. | ``string`` | Yes |
|``headers`` | The custom headers of the response. | [[]errorPage.Return.Header](#errorpagereturnheader) | No |
-{{% /table %}}
+{{}}
### ErrorPage.Return.Header
@@ -923,12 +927,12 @@ name: x-debug-original-statuses
value: ${upstream_status}
```
-{{% table %}}
+{{}}
|Field | Description | Type | Required |
| ---| ---| ---| --- |
|``name`` | The name of the header. | ``string`` | Yes |
|``value`` | The value of the header. Supported NGINX variable: ``$upstream_status`` . Variables must be enclosed in curly braces. For example: ``${upstream_status}``. | ``string`` | No |
-{{% /table %}}
+{{}}
## Using VirtualServer and VirtualServerRoute
@@ -938,7 +942,8 @@ For example, the following command creates a VirtualServer resource defined in `
```shell
kubectl apply -f cafe-virtual-server.yaml
-
+```
+```text
virtualserver.k8s.nginx.org "cafe" created
```
@@ -946,14 +951,15 @@ You can get the resource by running:
```shell
kubectl get virtualserver cafe
-
+```
+```text
NAME STATE HOST IP PORTS AGE
cafe Valid cafe.example.com 12.13.23.123 [80,443] 3m
```
-In the kubectl get and similar commands, you can also use the short name `vs` instead of `virtualserver`.
+In `kubectl get` and similar commands, you can use the short name `vs` instead of `virtualserver`.
-Working with VirtualServerRoute resources is analogous. In the kubectl commands, use `virtualserverroute` or the short name `vsr`.
+Similarly, for VirtualServerRoute you can use `virtualserverroute` or the short name `vsr`.
### Using Snippets
@@ -993,28 +999,14 @@ spec:
pass: coffee
```
-Snippets are intended to be used by advanced NGINX users who need more control over the generated NGINX configuration.
-
-However, because of the disadvantages described below, snippets are disabled by default. To use snippets, set the [`enable-snippets`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-enable-snippets) command-line argument.
-
-Disadvantages of using snippets:
-
-- *Complexity*. To use snippets, you will need to:
- - Understand NGINX configuration primitives and implement a correct NGINX configuration.
- - Understand how the IC generates NGINX configuration so that a snippet doesn't interfere with the other features in the configuration.
-- *Decreased robustness*. An incorrect snippet makes the NGINX config invalid which will lead to a failed reload. This will prevent any new configuration updates, including updates for the other VirtualServer and VirtualServerRoute resources until the snippet is fixed.
-- *Security implications*. Snippets give access to NGINX configuration primitives and those primitives are not validated by the Ingress Controller. For example, a snippet can configure NGINX to serve the TLS certificates and keys used for TLS termination for Ingress and VirtualServer resources.
-
-To help catch errors when using snippets, the Ingress Controller reports config reload errors in the logs as well as in the events and status field of VirtualServer and VirtualServerRoute resources. Additionally, a number of Prometheus metrics show the stats about failed reloads – `controller_nginx_last_reload_status` and `controller_nginx_reload_errors_total`.
-
-> Note that during a period when the NGINX config includes an invalid snippet, NGINX will continue to operate with the latest valid configuration.
+For additional information, view the [Advanced configuration with Snippets]({{< relref "configuration/ingress-resources/advanced-configuration-with-snippets.md" >}}) topic.
### Validation
Two types of validation are available for VirtualServer and VirtualServerRoute resources:
- *Structural validation* by the `kubectl` and Kubernetes API server.
-- *Comprehensive validation* by the Ingress Controller.
+- *Comprehensive validation* by NGINX Ingress Controller.
#### Structural Validation
@@ -1026,31 +1018,34 @@ If you try to create (or update) a resource that violates the structural schema
```shell
kubectl apply -f cafe-virtual-server.yaml
-
- error: error validating "cafe-virtual-server.yaml": error validating data: ValidationError(VirtualServer.spec.upstreams[0].port): invalid type for org.nginx.k8s.v1.VirtualServer.spec.upstreams.port: got "string", expected "integer"; if you choose to ignore these errors, turn validation off with --validate=false
+ ```
+ ```text
+ error: error validating "cafe-virtual-server.yaml": error validating data: ValidationError(VirtualServer.spec.upstreams[0].port): invalid type for org.nginx.k8s.v1.VirtualServer.spec.upstreams.port: got "string", expected "integer"; if you choose to ignore these errors, turn validation off with --validate=false
```
- Example of Kubernetes API server validation:
```shell
kubectl apply -f cafe-virtual-server.yaml --validate=false
-
- The VirtualServer "cafe" is invalid: []: Invalid value: map[string]interface {}{ ... }: validation failure list:
- spec.upstreams.port in body must be of type integer: "string"
+ ```
+ ```text
+ The VirtualServer "cafe" is invalid: []: Invalid value: map[string]interface {}{ ... }: validation failure list:
+ spec.upstreams.port in body must be of type integer: "string"
```
-If a resource is not rejected (it doesn't violate the structural schema), the Ingress Controller will validate it further.
+If a resource is not rejected (it doesn't violate the structural schema), NGINX Ingress Controller will validate it further.
#### Comprehensive Validation
-The Ingress Controller validates the fields of the VirtualServer and VirtualServerRoute resources. If a resource is invalid, the Ingress Controller will reject it: the resource will continue to exist in the cluster, but the Ingress Controller will ignore it.
+NGINX Ingress Controller validates the fields of the VirtualServer and VirtualServerRoute resources. If a resource is invalid, NGINX Ingress Controller will reject it: the resource will continue to exist in the cluster, but NGINX Ingress Controller will ignore it.
-You can check if the Ingress Controller successfully applied the configuration for a VirtualServer. For our example `cafe` VirtualServer, we can run:
+You can check if NGINX Ingress Controller successfully applied the configuration for a VirtualServer. For our example `cafe` VirtualServer, we can run:
```shell
kubectl describe vs cafe
-
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
@@ -1059,12 +1054,13 @@ Events:
Note how the events section includes a Normal event with the AddedOrUpdated reason that informs us that the configuration was successfully applied.
-If you create an invalid resource, the Ingress Controller will reject it and emit a Rejected event. For example, if you create a VirtualServer `cafe` with two upstream with the same name `tea`, you will get:
+If you create an invalid resource, NGINX Ingress Controller will reject it and emit a Rejected event. For example, if you create a VirtualServer `cafe` with two upstream with the same name `tea`, you will get:
```shell
kubectl describe vs cafe
-
-. . .
+```
+```text
+...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
@@ -1077,8 +1073,9 @@ Additionally, this information is also available in the `status` field of the Vi
```shell
kubectl describe vs cafe
-
-. . .
+```
+```text
+...
Status:
External Endpoints:
Ip: 12.13.23.123
@@ -1088,11 +1085,11 @@ Status:
State: Invalid
```
-The Ingress Controller validates VirtualServerRoute resources in a similar way.
+NGINX Ingress Controller validates VirtualServerRoute resources in a similar way.
-**Note**: If you make an existing resource invalid, the Ingress Controller will reject it and remove the corresponding configuration from NGINX.
+**Note**: If you make an existing resource invalid, NGINX Ingress Controller will reject it and remove the corresponding configuration from NGINX.
-## Customization via ConfigMap
+## Customization using ConfigMap
You can customize the NGINX configuration for VirtualServer and VirtualServerRoutes resources using the [ConfigMap](/nginx-ingress-controller/configuration/global-configuration/configmap-resource). Most of the ConfigMap keys are supported, with the following exceptions:
diff --git a/docs/content/installation/integrations/app-protect-waf/installation.md b/docs/content/installation/integrations/app-protect-waf/installation.md
index 98f1a632ff..5f48967649 100644
--- a/docs/content/installation/integrations/app-protect-waf/installation.md
+++ b/docs/content/installation/integrations/app-protect-waf/installation.md
@@ -68,7 +68,7 @@ Follow these steps to build the NGINX Controller Image with NGINX App Protect WA
### Makefile targets {#makefile-targets}
-{{}}
+{{}}
| Makefile Target | Description | Compatible Systems |
|---------------------------|-------------------------------------------------------------------|---------------------|
| **debian-image-nap-plus** | Builds a Debian-based image with NGINX Plus and the [NGINX App Protect WAF](/nginx-app-protect-waf/) module. | Debian |
@@ -81,13 +81,6 @@ Follow these steps to build the NGINX Controller Image with NGINX App Protect WA
{{}} For the complete list of _Makefile_ targets and customizable variables, see the [Building NGINX Ingress Controller]({{< relref "installation/building-nginx-ingress-controller.md#makefile-details" >}}) guide. {{}}
-If you intend to use [external references](/nginx-app-protect-waf/v4/configuration/#external-references) in NGINX App Protect WAF policies, you may want to provide a custom CA certificate to authenticate with the hosting server.
-
-To do so, place the `*.crt` file in the build folder and uncomment the lines following this comment:
-`#Uncomment the lines below if you want to install a custom CA certificate`
-
-{{}} External references are deprecated in NGINX Ingress Controller and will not be supported in future releases. {{}}
-
---
## Push the image to your private registry
From 20283762b7d3ab61d5c2d57ea3d5153c74688eee Mon Sep 17 00:00:00 2001
From: nginx-bot <68849795+nginx-bot@users.noreply.github.com>
Date: Thu, 13 Jun 2024 12:16:09 -0700
Subject: [PATCH 14/38] Docker image update d41d8cd9 (#5743)
---
build/Dockerfile | 8 ++++----
tests/Dockerfile | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/build/Dockerfile b/build/Dockerfile
index 935e53dde8..32bdabc8ff 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -14,7 +14,7 @@ FROM ghcr.io/nginxinc/k8s-common:nginx-opentracing-1.27.0@sha256:d9f6f930b7bfcc0
FROM ghcr.io/nginxinc/k8s-common:nginx-opentracing-1.27.0-alpine@sha256:5dc5c76384a775316c541995b145d4cef86d529934951319fd127f4d4fdb9ef7 as alpine-opentracing-lib
FROM ghcr.io/nginxinc/alpine-fips:0.1.0-alpine3.17@sha256:f00b3f266422feaaac7b733b46903bd19eb1cd1caa6991131576f5f767db76f8 as alpine-fips-3.17
FROM ghcr.io/nginxinc/alpine-fips:0.2.0-alpine3.19@sha256:1744ae3a8e795daf771f3f7df33b83160981545abb1f1597338e2769d06aa1cc as alpine-fips-3.19
-FROM redhat/ubi9-minimal@sha256:2636170dc55a0931d013014a72ae26c0c2521d4b61a28354b3e2e5369fa335a3 AS ubi-minimal
+FROM redhat/ubi9-minimal@sha256:a7d837b00520a32502ada85ae339e33510cdfdbc8d2ddf460cc838e12ec5fa5a AS ubi-minimal
FROM golang:1.22-alpine@sha256:9bdd5692d39acc3f8d0ea6f81327f87ac6b473dd29a2b6006df362bff48dd1f8 as golang-builder
@@ -204,7 +204,7 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
############################################# Base image for Debian with NGINX Plus #############################################
-FROM debian:12-slim@sha256:804194b909ef23fb995d9412c9378fb3505fe2427b70f3cc425339e48a828fca AS debian-plus
+FROM debian:12-slim@sha256:67f3931ad8cb1967beec602d8c0506af1e37e8d73c2a0b38b181ec5d8560d395 AS debian-plus
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
@@ -227,7 +227,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
############################################# Base image for Debian with NGINX Plus and App Protect WAF/DoS #############################################
-FROM debian:11-slim@sha256:0e75382930ceb533e2f438071307708e79dc86d9b8e433cc6dd1a96872f2651d as debian-plus-nap
+FROM debian:11-slim@sha256:acc5810124f0929ab44fc7913c0ad936b074cbd3eadf094ac120190862ba36c4 as debian-plus-nap
ARG NAP_MODULES
ARG NGINX_AGENT
@@ -480,7 +480,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
############################################# Base image for UBI with NGINX Plus and App Protect WAFv5 #############################################
-FROM redhat/ubi8@sha256:f4292f415f60632a0ff9c0646c4fa859d8b2e1e88a16faa90c6decd1951aea88 as ubi-8-plus-nap-v5
+FROM redhat/ubi8@sha256:143123d85045df426c5bbafc6863659880ebe276eb02c77ee868b88d08dbd05d as ubi-8-plus-nap-v5
ARG NAP_MODULES
ARG NGINX_AGENT
diff --git a/tests/Dockerfile b/tests/Dockerfile
index 5cb4aca587..1f497954d9 100644
--- a/tests/Dockerfile
+++ b/tests/Dockerfile
@@ -2,7 +2,7 @@
# this is here so we can grab the latest version of kind and have dependabot keep it up to date
FROM kindest/node:v1.30.0@sha256:047357ac0cfea04663786a612ba1eaba9702bef25227a794b52890dd8bcd692e
-FROM python:3.12@sha256:3966b81808d864099f802080d897cef36c01550472ab3955fdd716d1c665acd6
+FROM python:3.12@sha256:00389e020fe42a6c74a8f091ce9b28324422d084efdff26eabe93bc4ae9a110b
RUN apt-get update \
&& apt-get install -y curl git \
From 9f37c5f8206840bf5ec1fe41b9d59c1758c41144 Mon Sep 17 00:00:00 2001
From: Paul Abel <128620221+pdabelf5@users.noreply.github.com>
Date: Fri, 14 Jun 2024 08:52:04 +0100
Subject: [PATCH 15/38] add release workflow (#5742)
---
.github/workflows/ci.yml | 12 ++++--------
.github/workflows/update-docker-sha.yml | 23 +++++++++++++++++++++--
2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 16aec5331a..e76b6fc3ad 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -195,7 +195,7 @@ jobs:
with:
minor-label: "enhancement"
major-label: "change"
- publish: ${{ github.ref_type == 'tag' }}
+ publish: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
collapse-after: 50
variables: |
helm-chart=${{ needs.checks.outputs.chart_version }}
@@ -234,17 +234,17 @@ jobs:
- name: Download Syft
uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0
- if: github.ref_type == 'tag'
+ if: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
- name: Install Cosign
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
- if: github.ref_type == 'tag'
+ if: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
- name: Build binaries
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
with:
version: latest
- args: ${{ github.ref_type == 'tag' && 'release' || 'build --snapshot' }} --clean
+ args: build --snapshot --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GOPATH: ${{ needs.checks.outputs.go_path }}
@@ -256,10 +256,6 @@ jobs:
AWS_NAP_WAF_PUB_KEY: ${{ secrets.AWS_NAP_WAF_PUB_KEY }}
AWS_NAP_WAF_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_DOS_PRODUCT_CODE }}
AWS_NAP_WAF_DOS_PUB_KEY: ${{ secrets.AWS_NAP_WAF_DOS_PUB_KEY }}
- SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_COMMUNITY }}
- AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }}
- AZURE_STORAGE_KEY: ${{ secrets.AZURE_STORAGE_KEY }}
- AZURE_BUCKET_NAME: ${{ secrets.AZURE_BUCKET_NAME }}
GORELEASER_CURRENT_TAG: "v${{ needs.checks.outputs.ic_version }}"
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
diff --git a/.github/workflows/update-docker-sha.yml b/.github/workflows/update-docker-sha.yml
index 2f0b3245fb..7d08b9a74f 100644
--- a/.github/workflows/update-docker-sha.yml
+++ b/.github/workflows/update-docker-sha.yml
@@ -15,6 +15,8 @@ on:
dry_run:
type: boolean
default: false
+ schedule:
+ - cron: "0 1 * * 1-5" # 01:00 UTC Mon-Fri
defaults:
run:
@@ -24,15 +26,32 @@ permissions:
contents: read
jobs:
+ vars:
+ permissions:
+ contents: read
+ runs-on: ubuntu-22.04
+ outputs:
+ source_branch: ${{ steps.vars.outputs.source_branch }}
+ steps:
+ - name: Set vars
+ id: vars
+ run: |
+ source_branch=main
+ if ${{ inputs.source_branch }}; then
+ source_branch=${{ inputs.source_branch }}
+ fi
+ echo "source_branch=${source_branch}" >> $GITHUB_OUTPUT
+
update-docker-sha:
permissions:
contents: write
runs-on: ubuntu-22.04
+ needs: [vars]
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
with:
- ref: ${{ inputs.source_branch }}
+ ref: ${{ needs.vars.outputs.source_branch }}
- name: Update images
id: update_images
@@ -59,7 +78,7 @@ jobs:
token: ${{ secrets.NGINX_PAT }}
commit-message: Update docker images ${{ steps.update_images.outputs.docker_md5 }}
title: Docker image update ${{ steps.update_images.outputs.docker_md5 }}
- branch: chore/image-update-${{ inputs.source_branch }}-${{ steps.update_images.outputs.docker_md5 }}
+ branch: chore/image-update-${{ needs.vars.outputs.source_branch }}-${{ steps.update_images.outputs.docker_md5 }}
author: nginx-bot
labels: |
dependencies
From 5ab9425f3f75a2e580b308fbc615c8264ab106d9 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Mon, 17 Jun 2024 13:57:33 +0100
Subject: [PATCH 16/38] correct wafv5 release
---
.github/scripts/copy-images.sh | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/.github/scripts/copy-images.sh b/.github/scripts/copy-images.sh
index 67eb85342f..d5eaba3cc5 100755
--- a/.github/scripts/copy-images.sh
+++ b/.github/scripts/copy-images.sh
@@ -39,14 +39,12 @@ SOURCE_NAP_WAF_IMAGE_PREFIX=${SOURCE_NAP_WAF_IMAGE_PREFIX:-"nginx-ic-nap/nginx-p
SOURCE_NAP_WAFV5_IMAGE_PREFIX=${SOURCE_NAP_WAFV5_IMAGE_PREFIX:-"nginx-ic-nap-v5/nginx-plus-ingress"}
SOURCE_NAP_DOS_IMAGE_PREFIX=${SOURCE_NAP_DOS_IMAGE_PREFIX:-"nginx-ic-dos/nginx-plus-ingress"}
SOURCE_NAP_WAF_DOS_IMAGE_PREFIX=${SOURCE_NAP_WAF_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap/nginx-plus-ingress"}
-SOURCE_NAP_WAFV5_DOS_IMAGE_PREFIX=${SOURCE_NAP_WAFV5_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap-v5/nginx-plus-ingress"}
TARGET_PLUS_IMAGE_PREFIX=${TARGET_PLUS_IMAGE_PREFIX:-"nginx-ic/nginx-plus-ingress"}
TARGET_NAP_WAF_IMAGE_PREFIX=${TARGET_NAP_WAF_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
TARGET_NAP_WAFV5_IMAGE_PREFIX=${TARGET_NAP_WAFV5_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
TARGET_NAP_DOS_IMAGE_PREFIX=${TARGET_NAP_DOS_IMAGE_PREFIX:-"nginx-ic-dos/nginx-plus-ingress"}
TARGET_NAP_WAF_DOS_IMAGE_PREFIX=${TARGET_NAP_WAF_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap/nginx-plus-ingress"}
-TARGET_NAP_WAFV5_DOS_IMAGE_PREFIX=${TARGET_NAP_WAFV5_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap-v5/nginx-plus-ingress"}
declare -a OSS_TAG_POSTFIX_LIST=("" "-ubi" "-alpine")
declare -a PLUS_TAG_POSTFIX_LIST=("" "-ubi" "-alpine" "-alpine-fips")
@@ -188,29 +186,6 @@ if $PUBLISH_WAF; then
done
fi
done
- for postfix in "${NAP_WAFV5_TAG_POSTFIX_LIST[@]}"; do
- image=${SOURCE_REGISTRY}/${SOURCE_NAP_WAFV5_IMAGE_PREFIX}:${SOURCE_TAG}${postfix}
- echo "Processing image ${image}"
- new_tag=${TARGET_REGISTRY}/${TARGET_NAP_WAFV5_IMAGE_PREFIX}:${TARGET_TAG}${postfix}
- if $IS_IMMUTABLE && skopeo --override-os linux --override-arch amd64 inspect docker://${new_tag} > /dev/null 2>&1; then
- echo " ECR is immutable & tag ${new_tag} already exists, skipping."
- else
- echo " Pushing image NAP WAFV5 ${new_tag}..."
- if ! $DRY_RUN; then
- skopeo copy --retry-times 5 ${ARCH_OPTS} ${SOURCE_OPTS} ${TARGET_OPTS} docker://${image} docker://${new_tag}
- fi
- for tag in "${ADDITIONAL_TAGS[@]}"; do
- if [ -z "${tag}" ]; then
- continue
- fi
- additional_tag=${TARGET_REGISTRY}/${TARGET_NAP_WAFV5_IMAGE_PREFIX}:${tag}${postfix}
- echo " Pushing image NAP WAFV5 ${additional_tag}..."
- if ! $DRY_RUN; then
- skopeo copy --retry-times 5 ${ARCH_OPTS} ${SOURCE_OPTS} ${TARGET_OPTS} docker://${image} docker://${additional_tag}
- fi
- done
- fi
- done
else
echo "Skipping Publish Plus WAF flow"
fi
From dda4ac8121c6fc6b409e1f34644cd90a6df0658e Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Mon, 17 Jun 2024 17:14:16 +0100
Subject: [PATCH 17/38] renamed inputs on oss/plus build workflows
---
.github/workflows/build-base-images.yml | 16 +++++
.github/workflows/build-oss.yml | 52 ++++++++--------
.github/workflows/build-plus.yml | 60 ++++++++++---------
.github/workflows/cache-update.yml | 11 ++--
.github/workflows/ci.yml | 37 ++++++++----
.../{edge.yml => image-promotion.yml} | 31 ++++++----
6 files changed, 121 insertions(+), 86 deletions(-)
rename .github/workflows/{edge.yml => image-promotion.yml} (92%)
diff --git a/.github/workflows/build-base-images.yml b/.github/workflows/build-base-images.yml
index 0a5d0b4a22..969c0d0a4e 100644
--- a/.github/workflows/build-base-images.yml
+++ b/.github/workflows/build-base-images.yml
@@ -196,6 +196,22 @@ jobs:
- image: alpine-plus-nap-fips
platforms: "linux/amd64"
nap_modules: waf
+ - image: alpine-plus-nap-v5-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: debian-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-9-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
steps:
- name: Checkout Repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index 6e3e912565..593d3c1cb6 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -21,12 +21,14 @@ on:
branch:
required: true
type: string
- forked-workflow:
+ authenticated:
required: true
type: boolean
- docs-only:
- required: true
+ full-build:
+ description: Always build base image
+ required: false
type: boolean
+ default: false
defaults:
run:
@@ -65,7 +67,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -73,34 +75,35 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated }}
- name: Check if base images exist
id: base_exists
run: |
- if docker manifest inspect gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:${{ inputs.base-image-md5 }}-${{ inputs.image }}; then
+ base_image="gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:${{ inputs.base-image-md5 }}-${{ inputs.image }}"
+ echo "image=${base_image}"
+ if docker manifest inspect ${base_image}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated && ! inputs.full-build }}
- name: Build Base Container
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
with:
file: build/Dockerfile
context: "."
- cache-from: type=gha,scope=${{ inputs.image }}
cache-to: type=gha,scope=${{ inputs.image }},mode=max
target: common
- tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:${{ inputs.base-image-md5 }}-${{ inputs.image }}
+ tags: ${{ steps.base_exists.outputs.image }}
platforms: ${{ inputs.platforms }}
pull: true
push: true
+ no-cache: true
build-args: |
BUILD_OS=${{ inputs.image }}
- IC_VERSION=${{ inputs.tag }}
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.base_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 0 }}
- name: Docker meta
id: meta
@@ -113,6 +116,7 @@ jobs:
suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}
tags: |
type=raw,value=${{ inputs.tag }}
+ type=ref,event=pr
labels: |
org.opencontainers.image.description=NGINX Ingress Controller for Kubernetes
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/main/README.md
@@ -131,23 +135,22 @@ jobs:
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated && ! inputs.full-build }}
- name: Debug values
run: |
- echo "forked-workflow: ${{ inputs.forked-workflow }}"
- echo "docs-only: ${{ inputs.docs-only }}"
- echo "docs-only invert: ${{ ! inputs.docs-only }}"
+ echo "authenticated: ${{ inputs.authenticated }}"
echo "base_exists: ${{ steps.base_exists.outputs.exists }}"
echo "target_exists: ${{ steps.target_exists.outputs.exists }}"
- echo "all: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
+ echo "full-build: ${{ inputs.full-build }}"
+ echo "all: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ inputs.go-md5 }}
- if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
- name: Build Docker image
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
@@ -157,22 +160,21 @@ jobs:
context: "."
cache-from: type=gha,scope=${{ inputs.image }}
cache-to: type=gha,scope=${{ inputs.image }},mode=max
- target: goreleaser${{ ! inputs.forked-workflow && '-prebuilt' || '' }}
+ target: goreleaser${{ inputs.authenticated && '-prebuilt' || '' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
platforms: ${{ inputs.platforms }}
load: false
- push: ${{ ! inputs.forked-workflow }}
+ push: ${{ inputs.authenticated }}
pull: true
- no-cache: ${{ ! inputs.forked-workflow }}
- sbom: ${{ ! inputs.forked-workflow }}
+ sbom: ${{ inputs.authenticated }}
provenance: false
build-args: |
BUILD_OS=${{ inputs.image }}
- ${{ ! inputs.forked-workflow && format('PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:{0}-{1}', inputs.base-image-md5, inputs.image) || '' }}
+ ${{ inputs.authenticated && format('PREBUILT_BASE_IMG={0}', steps.base_exists.outputs.image) }}
IC_VERSION=${{ (github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/release-')) && 'CI' || steps.meta.outputs.version }}
- if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0
@@ -182,14 +184,14 @@ jobs:
format: "sarif"
output: "trivy-results-${{ inputs.image }}.sarif"
ignore-unfixed: "true"
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
+ if: ${{ inputs.authenticated && steps.build-push.conclusion == 'success' }}
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
continue-on-error: true
with:
sarif_file: "trivy-results-${{ inputs.image }}.sarif"
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
+ if: ${{ inputs.authenticated && steps.build-push.conclusion == 'success' }}
- name: Upload Scan Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 7711788624..2492cdab6f 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -21,18 +21,20 @@ on:
branch:
required: false
type: string
- forked-workflow:
- required: false
- type: boolean
nap-modules:
required: false
type: string
target:
required: true
type: string
- docs-only:
+ authenticated:
required: true
type: boolean
+ full-build:
+ description: Always build base image
+ required: false
+ type: boolean
+ default: false
defaults:
run:
@@ -70,7 +72,7 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated }}
- name: Login to GCR
uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
@@ -78,7 +80,7 @@ jobs:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated }}
- name: NAP modules
id: nap_modules
@@ -92,34 +94,35 @@ jobs:
- name: Check if base images exist
id: base_exists
run: |
- if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}; then
+ base_image="gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}"
+ echo "image=${base_image}"
+ if docker pull ${base_image}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated && ! inputs.full-build }}
- name: Build Base Container
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
with:
file: build/Dockerfile
context: "."
- cache-from: type=gha,scope=${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
cache-to: type=gha,scope=${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
target: common
- tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}
+ tags: ${{ steps.base_exists.outputs.image }}
platforms: ${{ inputs.platforms }}
pull: true
push: true
+ no-cache: true
build-args: |
BUILD_OS=${{ inputs.image }}
- IC_VERSION=${{ steps.meta.outputs.version }}
${{ inputs.nap-modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
secrets: |
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
"nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
${{ inputs.nap-modules != '' && contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.base_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 0 }}
- name: Docker meta
id: meta
@@ -131,6 +134,7 @@ jobs:
suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}${{ contains(inputs.target, 'aws') && '-mktpl' || '' }}${{ contains(inputs.image, 'fips') && '-fips' || ''}}
tags: |
type=raw,value=${{ inputs.tag }}
+ type=ref,event=pr
labels: |
org.opencontainers.image.description=NGINX Plus Ingress Controller for Kubernetes
env:
@@ -144,23 +148,22 @@ jobs:
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
- if: ${{ ! inputs.forked-workflow || ! inputs.docs-only }}
+ if: ${{ inputs.authenticated && ! inputs.full-build }}
- name: Debug values
run: |
- echo "forked-workflow: ${{ inputs.forked-workflow }}"
- echo "docs-only: ${{ inputs.docs-only }}"
- echo "docs-only invert: ${{ ! inputs.docs-only }}"
+ echo "authenticated: ${{ inputs.authenticated }}"
echo "base_exists: ${{ steps.base_exists.outputs.exists }}"
echo "target_exists: ${{ steps.target_exists.outputs.exists }}"
- echo "all: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
+ echo "full-build: ${{ inputs.full-build }}"
+ echo "all: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ inputs.go-md5 }}
- if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
- name: Build Docker image
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
@@ -170,36 +173,35 @@ jobs:
context: "."
cache-from: type=gha,scope=${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
cache-to: type=gha,scope=${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
- target: ${{ inputs.target }}${{ ! inputs.forked-workflow && '-prebuilt' || '' }}
+ target: ${{ inputs.target }}${{ inputs.authenticated && '-prebuilt' || '' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
annotations: ${{ steps.meta.outputs.annotations }}
platforms: ${{ inputs.platforms }}
load: false
- push: ${{ ! inputs.forked-workflow }}
+ push: ${{ inputs.authenticated }}
pull: true
- no-cache: ${{ ! inputs.forked-workflow }}
- sbom: ${{ ! inputs.forked-workflow }}
+ sbom: ${{ inputs.authenticated }}
provenance: false
build-args: |
BUILD_OS=${{ inputs.image }}
- ${{ ! inputs.forked-workflow && format('PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:{0}-{1}{2}', inputs.base-image-md5, inputs.image, steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '') || '' }}
+ ${{ inputs.authenticated && format('PREBUILT_BASE_IMG={0}', steps.base_exists.outputs.image ) }}
IC_VERSION=${{ steps.meta.outputs.version }}
- ${{ inputs.nap_modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
- ${{ (contains(inputs.target, 'aws') && inputs.nap_modules != '') && format('NAP_MODULES_AWS={0}', steps.nap_modules.outputs.modules) || '' }}
+ ${{ inputs.nap-modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
+ ${{ (contains(inputs.target, 'aws') && inputs.nap-modules != '') && format('NAP_MODULES_AWS={0}', steps.nap_modules.outputs.modules) || '' }}
${{ contains(inputs.image, 'v5') && 'WAF_VERSION=v5' || '' }}
secrets: |
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
"nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
${{ contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ ! inputs.docs-only || inputs.forked-workflow || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
- name: Extract image name for Trivy
id: trivy-tag
run: |
tag=$(echo $DOCKER_METADATA_OUTPUT_JSON | jq -r '[ .tags[] | select(contains("f5-gcs-7899"))] | .[0]')
echo "tag=$tag" >> $GITHUB_OUTPUT
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
+ if: ${{ inputs.authenticated && steps.build-push.conclusion == 'success' }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0
@@ -209,14 +211,14 @@ jobs:
format: "sarif"
output: "trivy-results-${{ inputs.image }}.sarif"
ignore-unfixed: "true"
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
+ if: ${{ inputs.authenticated && steps.build-push.conclusion == 'success' }}
- name: Upload Trivy scan results to GitHub Security tab
uses: github/codeql-action/upload-sarif@530d4feaa9c62aaab2d250371e2061eb7a172363 # v3.25.9
continue-on-error: true
with:
sarif_file: "trivy-results-${{ inputs.image }}.sarif"
- if: ${{ ( ! inputs.forked-workflow || ! inputs.docs-only ) && steps.build-push.conclusion == 'success' }}
+ if: ${{ inputs.authenticated && steps.build-push.conclusion == 'success' }}
- name: Upload Scan Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
diff --git a/.github/workflows/cache-update.yml b/.github/workflows/cache-update.yml
index e5f828bd9e..1309c251c8 100644
--- a/.github/workflows/cache-update.yml
+++ b/.github/workflows/cache-update.yml
@@ -51,8 +51,7 @@ jobs:
image: ${{ matrix.image }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- forked-workflow: true
- docs-only: false
+ authenticated: false
tag: "edge"
branch: ${{ github.ref }}
permissions:
@@ -83,10 +82,9 @@ jobs:
target: ${{ matrix.target }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- docs-only: false
+ authenticated: false
tag: "edge"
branch: ${{ github.ref }}
- forked-workflow: true
permissions:
contents: read
security-events: write
@@ -139,11 +137,10 @@ jobs:
target: ${{ matrix.target }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- nap_modules: ${{ matrix.nap_modules }}
- docs-only: false
+ nap-modules: ${{ matrix.nap_modules }}
+ authenticated: false
tag: "edge"
branch: ${{ github.ref }}
- forked-workflow: true
permissions:
contents: read
security-events: write
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e76b6fc3ad..e5732cde72 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,15 +1,17 @@
name: CI
on:
- push:
- branches:
- - main
- - release-*
pull_request:
branches:
- main
- release-*
merge_group:
+ workflow_dispatch:
+ inputs:
+ force:
+ description: "Force rebuild"
+ required: false
+ default: "false"
defaults:
run:
@@ -284,8 +286,8 @@ jobs:
image: ${{ matrix.image }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- docs-only: ${{ needs.checks.outputs.docs_only == 'true' }}
+ authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ full-build: ${{ inputs.force }}
tag: ${{ needs.checks.outputs.build_tag }}
branch: ${{ github.head_ref && github.head_ref || github.ref }}
permissions:
@@ -318,8 +320,8 @@ jobs:
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
branch: ${{ github.head_ref && github.head_ref || github.ref }}
tag: ${{ needs.checks.outputs.build_tag }}
- forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- docs-only: ${{ needs.checks.outputs.docs_only == 'true' }}
+ authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ full-build: ${{ inputs.force }}
permissions:
contents: read
security-events: write
@@ -391,8 +393,8 @@ jobs:
branch: ${{ github.head_ref && github.head_ref || github.ref }}
tag: ${{ needs.checks.outputs.build_tag }}
nap-modules: ${{ matrix.nap_modules }}
- forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- docs-only: ${{ needs.checks.outputs.docs_only == 'true' }}
+ authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ full-build: ${{ inputs.force }}
permissions:
contents: read
security-events: write
@@ -535,7 +537,7 @@ jobs:
if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
setup-matrix:
- if: ${{ needs.checks.outputs.docs_only != 'true' }}
+ if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: Setup Matrix for Smoke Tests
runs-on: ubuntu-22.04
needs: [binaries, checks]
@@ -593,7 +595,7 @@ jobs:
if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
smoke-tests:
- if: ${{ needs.checks.outputs.docs_only != 'true' }}
+ if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
runs-on: ubuntu-22.04
needs: [checks, setup-matrix, build-docker, build-docker-plus, build-docker-nap]
@@ -749,4 +751,13 @@ jobs:
target_tag: ${{ needs.checks.outputs.stable_tag }}
dry_run: false
secrets: inherit
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 0 && needs.checks.outputs.docs_only == 'false') }}
+
+ trigger-image-promotion:
+ name: Promote images on Force Run
+ needs: [build-docker,build-docker-plus,build-docker-nap,smoke-results]
+ permissions:
+ contents: read # To checkout repository
+ id-token: write # To sign into Google Container Registry
+ uses: ./.github/workflows/image-promotion.yml
+ if: ${{ inputs.force }}
diff --git a/.github/workflows/edge.yml b/.github/workflows/image-promotion.yml
similarity index 92%
rename from .github/workflows/edge.yml
rename to .github/workflows/image-promotion.yml
index f12e97a127..37596fa06a 100644
--- a/.github/workflows/edge.yml
+++ b/.github/workflows/image-promotion.yml
@@ -1,16 +1,23 @@
+# This workflow will:
+# - build images for forked workflows
+# - tag stable for forked workflows
+# - tag edge for main workflows
+# - tag release branch name for release branch workflows
+# - release edge images & helm charts for edge
+
on:
- pull_request:
+ push:
branches:
- main
- types:
- - closed
+ - release-*
+ workflow_call:
defaults:
run:
shell: bash
concurrency:
- group: ${{ github.ref_name }}-edge
+ group: ${{ github.ref_name }}-image-promotion
cancel-in-progress: true
permissions:
@@ -19,7 +26,6 @@ permissions:
jobs:
checks:
name: Checks and variables
- if: github.event.pull_request.merged == true
runs-on: ubuntu-22.04
permissions:
contents: read
@@ -107,8 +113,7 @@ jobs:
image: ${{ matrix.image }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- forked-workflow: false
- docs-only: false
+ authenticated: true
tag: ${{ needs.checks.outputs.build_tag }}
branch: ${{ github.ref }}
permissions:
@@ -140,8 +145,7 @@ jobs:
target: ${{ matrix.target }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- forked-workflow: false
- docs-only: false
+ authenticated: true
tag: ${{ needs.checks.outputs.build_tag }}
branch: ${{ github.ref }}
permissions:
@@ -198,8 +202,7 @@ jobs:
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
nap-modules: ${{ matrix.nap_modules }}
- forked-workflow: false
- docs-only: false
+ authenticated: true
tag: ${{ needs.checks.outputs.build_tag }}
branch: ${{ github.ref }}
permissions:
@@ -231,11 +234,12 @@ jobs:
uses: ./.github/workflows/retag-images.yml
with:
source_tag: ${{ needs.checks.outputs.stable_tag }}
- target_tag: "edge"
+ target_tag: ${{ github.ref_name == github.event.repository.default_branch && 'edge' || github.ref_name }}
dry_run: false
secrets: inherit
release-oss:
+ if: ${{ github.ref_name == github.event.repository.default_branch }}
name: Release Docker OSS
needs: [checks, build-docker]
uses: ./.github/workflows/oss-release.yml
@@ -255,6 +259,7 @@ jobs:
secrets: inherit
release-plus:
+ if: ${{ github.ref_name == github.event.repository.default_branch }}
name: Release Docker Plus
needs: [checks, build-docker-plus, build-docker-nap ]
uses: ./.github/workflows/plus-release.yml
@@ -273,6 +278,7 @@ jobs:
secrets: inherit
publish-helm-chart:
+ if: ${{ github.ref_name == github.event.repository.default_branch }}
name: Publish Helm Chart
needs: [checks ]
uses: ./.github/workflows/publish-helm.yml
@@ -287,6 +293,7 @@ jobs:
secrets: inherit
certify-openshift-images:
+ if: ${{ github.ref_name == github.event.repository.default_branch }}
name: Certify OpenShift UBI images
runs-on: ubuntu-22.04
needs: [release-oss]
From c0db353341e8b5803503e025c0c5e9483b13be6d Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Mon, 17 Jun 2024 17:17:30 +0100
Subject: [PATCH 18/38] correct workflow permissions
---
.github/workflows/ci.yml | 3 +++
.github/workflows/image-promotion.yml | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e5732cde72..0a71fc1b0c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -759,5 +759,8 @@ jobs:
permissions:
contents: read # To checkout repository
id-token: write # To sign into Google Container Registry
+ actions: read
+ packages: write
+ security-events: write
uses: ./.github/workflows/image-promotion.yml
if: ${{ inputs.force }}
diff --git a/.github/workflows/image-promotion.yml b/.github/workflows/image-promotion.yml
index 37596fa06a..2ece0be435 100644
--- a/.github/workflows/image-promotion.yml
+++ b/.github/workflows/image-promotion.yml
@@ -150,8 +150,10 @@ jobs:
branch: ${{ github.ref }}
permissions:
contents: read
+ actions: read
security-events: write
id-token: write
+ packages: write
secrets: inherit
build-docker-nap:
@@ -207,8 +209,10 @@ jobs:
branch: ${{ github.ref }}
permissions:
contents: read
+ actions: read
security-events: write
id-token: write
+ packages: write
secrets: inherit
tag-stable:
From ce236d8c7d899d5c2b695124b988a82a42bb46ea Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Mon, 17 Jun 2024 17:20:27 +0100
Subject: [PATCH 19/38] additional permissions for workflow
---
.github/workflows/ci.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0a71fc1b0c..3c977c2f50 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -757,10 +757,10 @@ jobs:
name: Promote images on Force Run
needs: [build-docker,build-docker-plus,build-docker-nap,smoke-results]
permissions:
- contents: read # To checkout repository
+ contents: write # for pushing to Helm Charts repository
id-token: write # To sign into Google Container Registry
actions: read
- packages: write
+ packages: write # for helm to push to GHCR
security-events: write
uses: ./.github/workflows/image-promotion.yml
if: ${{ inputs.force }}
From 6e9a640509de5c9723bfb0ef4058201f2a3673fb Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 09:10:50 +0100
Subject: [PATCH 20/38] remove duplicate md5sum
---
.github/scripts/variables.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/scripts/variables.sh b/.github/scripts/variables.sh
index 42b60a8b31..726ed04d8b 100755
--- a/.github/scripts/variables.sh
+++ b/.github/scripts/variables.sh
@@ -30,7 +30,7 @@ get_chart_md5() {
}
get_actions_md5() {
- find .github .github/data/version.txt -type f -exec md5sum {} + | LC_ALL=C sort | md5sum | awk '{ print $1 }'
+ find .github -type f -exec md5sum {} + | LC_ALL=C sort | md5sum | awk '{ print $1 }'
}
get_build_tag() {
From fe66b7dbe92cda0fe46e14f541568603ff97d102 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 09:58:38 +0100
Subject: [PATCH 21/38] remove unused cosign & syft downloads
---
.github/workflows/ci.yml | 8 --------
1 file changed, 8 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3c977c2f50..773400c98a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -234,14 +234,6 @@ jobs:
go-version-file: go.mod
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- - name: Download Syft
- uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0
- if: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
-
- - name: Install Cosign
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
- if: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
-
- name: Build binaries
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
with:
From 5c45b0b2b925fe3f45d4a56a7ae05e2290e796cf Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 10:37:57 +0100
Subject: [PATCH 22/38] fix image exists conditionals in ci
---
.github/workflows/build-oss.yml | 16 ++++------
.github/workflows/build-plus.yml | 16 ++++------
.github/workflows/ci.yml | 43 +++++++++++++++------------
.github/workflows/image-promotion.yml | 8 ++---
4 files changed, 39 insertions(+), 44 deletions(-)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index 593d3c1cb6..d0aff717ba 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -83,9 +83,7 @@ jobs:
base_image="gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:${{ inputs.base-image-md5 }}-${{ inputs.image }}"
echo "image=${base_image}"
if docker manifest inspect ${base_image}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ inputs.authenticated && ! inputs.full-build }}
@@ -103,7 +101,7 @@ jobs:
no-cache: true
build-args: |
BUILD_OS=${{ inputs.image }}
- if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 'true' }}
- name: Docker meta
id: meta
@@ -131,9 +129,7 @@ jobs:
id: target_exists
run: |
if docker pull ${{ steps.meta.outputs.tags }}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ inputs.authenticated && ! inputs.full-build }}
@@ -143,14 +139,14 @@ jobs:
echo "base_exists: ${{ steps.base_exists.outputs.exists }}"
echo "target_exists: ${{ steps.target_exists.outputs.exists }}"
echo "full-build: ${{ inputs.full-build }}"
- echo "all: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
+ echo "all: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}"
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ inputs.go-md5 }}
- if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Build Docker image
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
@@ -174,7 +170,7 @@ jobs:
BUILD_OS=${{ inputs.image }}
${{ inputs.authenticated && format('PREBUILT_BASE_IMG={0}', steps.base_exists.outputs.image) }}
IC_VERSION=${{ (github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/release-')) && 'CI' || steps.meta.outputs.version }}
- if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 2492cdab6f..bbb1d5b18b 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -97,9 +97,7 @@ jobs:
base_image="gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}"
echo "image=${base_image}"
if docker pull ${base_image}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ inputs.authenticated && ! inputs.full-build }}
@@ -122,7 +120,7 @@ jobs:
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
"nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
${{ inputs.nap-modules != '' && contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 'true' }}
- name: Docker meta
id: meta
@@ -144,9 +142,7 @@ jobs:
id: target_exists
run: |
if docker pull ${{ steps.meta.outputs.tags }}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ inputs.authenticated && ! inputs.full-build }}
@@ -156,14 +152,14 @@ jobs:
echo "base_exists: ${{ steps.base_exists.outputs.exists }}"
echo "target_exists: ${{ steps.target_exists.outputs.exists }}"
echo "full-build: ${{ inputs.full-build }}"
- echo "all: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}"
+ echo "all: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}"
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ inputs.go-md5 }}
- if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Build Docker image
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
@@ -194,7 +190,7 @@ jobs:
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
"nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
${{ contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 0 || steps.target_exists.outputs.exists != 0 }}
+ if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Extract image name for Trivy
id: trivy-tag
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3c977c2f50..e1272f186a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -146,9 +146,9 @@ jobs:
id: stable_exists
run: |
if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress:${{ steps.vars.outputs.stable_tag }}; then
- echo "exists=0" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=false" >> $GITHUB_OUTPUT
fi
if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
@@ -446,16 +446,14 @@ jobs:
id: stable_exists
run: |
if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
- name: Pull build image
run: |
docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
- if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 0 }}
+ if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 'true' }}
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
@@ -491,7 +489,7 @@ jobs:
run: |
kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
- if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Install Chart
run: >
@@ -505,12 +503,12 @@ jobs:
--set controller.telemetryReporting.enable=false
--wait
working-directory: ${{ github.workspace }}/charts/nginx-ingress
- if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Expose Test Ingresses
run: |
kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
- if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Test HTTP
run: |
@@ -522,7 +520,7 @@ jobs:
fi
printf '.'; counter=$(($counter+1)); sleep 5;
done
- if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Test HTTPS
run: |
@@ -534,7 +532,7 @@ jobs:
fi
printf '.'; counter=$(($counter+1)); sleep 5;
done
- if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
setup-matrix:
if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
@@ -598,7 +596,12 @@ jobs:
if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
runs-on: ubuntu-22.04
- needs: [checks, setup-matrix, build-docker, build-docker-plus, build-docker-nap]
+ needs:
+ - checks
+ - setup-matrix
+ - build-docker
+ - build-docker-plus
+ - build-docker-nap
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
@@ -637,9 +640,7 @@ jobs:
id: stable_exists
run: |
if docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.stable_tag }}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
@@ -653,7 +654,7 @@ jobs:
- name: Pull build image
run: |
docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
@@ -716,7 +717,7 @@ jobs:
k8s-version: ${{ matrix.k8s }}
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- if: ${{ steps.stable_exists.outputs.exists != 0 && needs.checks.outputs.docs_only == 'false' }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Upload Test Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
@@ -751,11 +752,15 @@ jobs:
target_tag: ${{ needs.checks.outputs.stable_tag }}
dry_run: false
secrets: inherit
- if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 0 && needs.checks.outputs.docs_only == 'false') }}
+ if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
trigger-image-promotion:
name: Promote images on Force Run
- needs: [build-docker,build-docker-plus,build-docker-nap,smoke-results]
+ needs:
+ - build-docker
+ - build-docker-plus
+ - build-docker-nap
+ - smoke-results
permissions:
contents: write # for pushing to Helm Charts repository
id-token: write # To sign into Google Container Registry
diff --git a/.github/workflows/image-promotion.yml b/.github/workflows/image-promotion.yml
index 2ece0be435..9f961b5ecd 100644
--- a/.github/workflows/image-promotion.yml
+++ b/.github/workflows/image-promotion.yml
@@ -89,9 +89,7 @@ jobs:
id: stable_exists
run: |
if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress:${{ steps.vars.outputs.stable_tag }}; then
- echo "exists=0" >> $GITHUB_OUTPUT
- else
- echo "exists=1" >> $GITHUB_OUTPUT
+ echo "exists=true" >> $GITHUB_OUTPUT
fi
build-docker:
@@ -265,7 +263,7 @@ jobs:
release-plus:
if: ${{ github.ref_name == github.event.repository.default_branch }}
name: Release Docker Plus
- needs: [checks, build-docker-plus, build-docker-nap ]
+ needs: [checks, build-docker-plus, build-docker-nap]
uses: ./.github/workflows/plus-release.yml
with:
nginx_registry: true
@@ -284,7 +282,7 @@ jobs:
publish-helm-chart:
if: ${{ github.ref_name == github.event.repository.default_branch }}
name: Publish Helm Chart
- needs: [checks ]
+ needs: [checks]
uses: ./.github/workflows/publish-helm.yml
with:
branch: ${{ github.ref_name }}
From 86b0264d4556729ff9ec6657e66d7aae988e5176 Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 10:48:56 +0100
Subject: [PATCH 23/38] add debug output
---
.github/workflows/ci.yml | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e1272f186a..85d3b0c5ba 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -147,11 +147,25 @@ jobs:
run: |
if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress:${{ steps.vars.outputs.stable_tag }}; then
echo "exists=true" >> $GITHUB_OUTPUT
- else
- echo "exists=false" >> $GITHUB_OUTPUT
fi
if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
+ - name: Output variables
+ run: |
+ echo docs_only: ${{ github.event.pull_request && steps.docs.outputs.docs_only == 'true' }}
+ echo k8s_latest: ${{ steps.vars.outputs.k8s_latest }}
+ echo latest_kindest_node_versions: ${{ steps.vars.outputs.latest_kindest_node_versions }}
+ echo go_path: ${{ steps.vars.outputs.go_path }}
+ echo go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
+ echo binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
+ echo chart_version: ${{ steps.vars.outputs.chart_version }}
+ echo ic_version: ${{ steps.vars.outputs.ic_version }}
+ echo docker_md5: ${{ steps.vars.outputs.docker_md5 }}
+ echo build_tag: ${{ steps.vars.outputs.build_tag }}
+ echo stable_tag: ${{ steps.vars.outputs.stable_tag }}
+ echo forked_workflow: ${{ steps.vars.outputs.forked_workflow }}
+ echo stable_image_exists: ${{ steps.stable_exists.outputs.exists }}
+
unit-tests:
name: Unit Tests
runs-on: ubuntu-22.04
From 4e16ff5c5e4e3dbcc43b394d456e90214c616290 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:29:49 +0100
Subject: [PATCH 24/38] ensure base image variable is set
---
.github/workflows/build-oss.yml | 2 +-
.github/workflows/build-plus.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index d0aff717ba..ec0fec9183 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -81,7 +81,7 @@ jobs:
id: base_exists
run: |
base_image="gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/oss:${{ inputs.base-image-md5 }}-${{ inputs.image }}"
- echo "image=${base_image}"
+ echo "image=${base_image}" >> $GITHUB_OUTPUT
if docker manifest inspect ${base_image}; then
echo "exists=true" >> $GITHUB_OUTPUT
fi
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index bbb1d5b18b..6897851812 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -95,7 +95,7 @@ jobs:
id: base_exists
run: |
base_image="gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/plus:${{ inputs.base-image-md5 }}-${{ inputs.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}"
- echo "image=${base_image}"
+ echo "image=${base_image}" >> $GITHUB_OUTPUT
if docker pull ${base_image}; then
echo "exists=true" >> $GITHUB_OUTPUT
fi
From e36aa3e081b5ce2c460f919ed0871127f9c35e8f Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:36:03 +0100
Subject: [PATCH 25/38] simplify workflow for debugging
---
.github/workflows/ci.yml | 1014 +++++++++++++++++++-------------------
1 file changed, 507 insertions(+), 507 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7deeaffba2..f0069a5204 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -191,42 +191,42 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }} # required
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- release-notes:
- name: Release Notes
- runs-on: ubuntu-22.04
- needs: [checks, unit-tests]
- outputs:
- release-url: ${{ steps.release-notes.outputs.release-url }}
- permissions:
- contents: write # for lucacome/draft-release
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- with:
- fetch-depth: 0
-
- - name: Create/Update Draft
- uses: lucacome/draft-release@8a63d32c79a171ae6048e614a8988f0ac3ed56d4 # v1.1.0
- id: release-notes
- with:
- minor-label: "enhancement"
- major-label: "change"
- publish: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
- collapse-after: 50
- variables: |
- helm-chart=${{ needs.checks.outputs.chart_version }}
- notes-footer: |
- ## Upgrade
- - For NGINX, use the {{version}} images from our [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/tags?page=1&ordering=last_updated&name={{version-number}}), [GitHub Container](https://github.com/nginxinc/kubernetes-ingress/pkgs/container/kubernetes-ingress), [Amazon ECR Public Gallery](https://gallery.ecr.aws/nginx/nginx-ingress) or [Quay.io](https://quay.io/repository/nginx/nginx-ingress).
- - For NGINX Plus, use the {{version}} images from the F5 Container registry, the [AWS Marketplace](https://aws.amazon.com/marketplace/search/?CREATOR=741df81b-dfdc-4d36-b8da-945ea66b522c&FULFILLMENT_OPTION_TYPE=CONTAINER&filters=CREATOR%2CFULFILLMENT_OPTION_TYPE), the [GCP Marketplace](https://console.cloud.google.com/marketplace/browse?filter=partner:F5,%20Inc.&filter=solution-type:k8s&filter=category:networking) or build your own image using the {{version}} source code.
- - For Helm, use version {{helm-chart}} of the chart.
-
- ## Resources
- - Documentation -- https://docs.nginx.com/nginx-ingress-controller/
- - Configuration examples -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/examples
- - Helm Chart -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/charts/nginx-ingress
- - Operator -- https://github.com/nginxinc/nginx-ingress-helm-operator
- if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
+ # release-notes:
+ # name: Release Notes
+ # runs-on: ubuntu-22.04
+ # needs: [checks, unit-tests]
+ # outputs:
+ # release-url: ${{ steps.release-notes.outputs.release-url }}
+ # permissions:
+ # contents: write # for lucacome/draft-release
+ # steps:
+ # - name: Checkout Repository
+ # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ # with:
+ # fetch-depth: 0
+
+ # - name: Create/Update Draft
+ # uses: lucacome/draft-release@8a63d32c79a171ae6048e614a8988f0ac3ed56d4 # v1.1.0
+ # id: release-notes
+ # with:
+ # minor-label: "enhancement"
+ # major-label: "change"
+ # publish: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
+ # collapse-after: 50
+ # variables: |
+ # helm-chart=${{ needs.checks.outputs.chart_version }}
+ # notes-footer: |
+ # ## Upgrade
+ # - For NGINX, use the {{version}} images from our [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/tags?page=1&ordering=last_updated&name={{version-number}}), [GitHub Container](https://github.com/nginxinc/kubernetes-ingress/pkgs/container/kubernetes-ingress), [Amazon ECR Public Gallery](https://gallery.ecr.aws/nginx/nginx-ingress) or [Quay.io](https://quay.io/repository/nginx/nginx-ingress).
+ # - For NGINX Plus, use the {{version}} images from the F5 Container registry, the [AWS Marketplace](https://aws.amazon.com/marketplace/search/?CREATOR=741df81b-dfdc-4d36-b8da-945ea66b522c&FULFILLMENT_OPTION_TYPE=CONTAINER&filters=CREATOR%2CFULFILLMENT_OPTION_TYPE), the [GCP Marketplace](https://console.cloud.google.com/marketplace/browse?filter=partner:F5,%20Inc.&filter=solution-type:k8s&filter=category:networking) or build your own image using the {{version}} source code.
+ # - For Helm, use version {{helm-chart}} of the chart.
+
+ # ## Resources
+ # - Documentation -- https://docs.nginx.com/nginx-ingress-controller/
+ # - Configuration examples -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/examples
+ # - Helm Chart -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/charts/nginx-ingress
+ # - Operator -- https://github.com/nginxinc/nginx-ingress-helm-operator
+ # if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
binaries:
name: Build Binaries
@@ -304,474 +304,474 @@ jobs:
packages: write
secrets: inherit
- build-docker-plus:
- name: Build Docker Plus
- needs: [binaries, checks]
- strategy:
- fail-fast: false
- matrix:
- image: [debian-plus, alpine-plus, alpine-plus-fips]
- platforms: ["linux/arm64, linux/amd64"]
- target: [goreleaser, aws]
- include:
- - image: ubi-plus
- platforms: "linux/arm64, linux/amd64, linux/s390x"
- target: goreleaser
- uses: ./.github/workflows/build-plus.yml
- with:
- platforms: ${{ matrix.platforms }}
- image: ${{ matrix.image }}
- target: ${{ matrix.target }}
- go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- branch: ${{ github.head_ref && github.head_ref || github.ref }}
- tag: ${{ needs.checks.outputs.build_tag }}
- authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- full-build: ${{ inputs.force }}
- permissions:
- contents: read
- security-events: write
- id-token: write
- secrets: inherit
-
- build-docker-nap:
- name: Build Docker NAP
- needs: [binaries, checks]
- strategy:
- fail-fast: false
- matrix:
- image: [debian-plus-nap]
- platforms: ["linux/amd64"]
- target: [goreleaser, aws]
- nap_modules: [dos, waf, "waf,dos"]
- include:
- - image: ubi-9-plus-nap
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- - image: ubi-8-plus-nap
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: dos
- - image: ubi-8-plus-nap
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: "waf,dos"
- - image: ubi-9-plus-nap
- target: aws
- platforms: "linux/amd64"
- nap_modules: waf
- - image: ubi-8-plus-nap
- target: aws
- platforms: "linux/amd64"
- nap_modules: dos
- - image: ubi-8-plus-nap
- target: aws
- platforms: "linux/amd64"
- nap_modules: "waf,dos"
- - image: alpine-plus-nap-fips
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- - image: alpine-plus-nap-v5-fips
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- - image: debian-plus-nap-v5
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- - image: ubi-9-plus-nap-v5
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- - image: ubi-8-plus-nap-v5
- target: goreleaser
- platforms: "linux/amd64"
- nap_modules: waf
- uses: ./.github/workflows/build-plus.yml
- with:
- platforms: ${{ matrix.platforms }}
- image: ${{ matrix.image }}
- target: ${{ matrix.target }}
- go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- branch: ${{ github.head_ref && github.head_ref || github.ref }}
- tag: ${{ needs.checks.outputs.build_tag }}
- nap-modules: ${{ matrix.nap_modules }}
- authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- full-build: ${{ inputs.force }}
- permissions:
- contents: read
- security-events: write
- id-token: write
- secrets: inherit
-
- helm-tests:
- if: ${{ needs.checks.outputs.docs_only != 'true' }}
- name: Helm Tests ${{ matrix.base-os }}
- runs-on: ubuntu-22.04
- needs: [checks, binaries, build-docker, build-docker-plus]
- strategy:
- fail-fast: false
- matrix:
- include:
- - base-os: debian
- image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
- tag: ${{ needs.checks.outputs.build_tag }}
- type: oss
- - base-os: debian-plus
- image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-plus-ingress
- tag: ${{ needs.checks.outputs.build_tag }}
- type: plus
- permissions:
- contents: read
- id-token: write
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- - name: Authenticate to Google Cloud
- id: auth
- uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
- with:
- token_format: access_token
- workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
- service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
-
- - name: Login to GCR
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: gcr.io
- username: oauth2accesstoken
- password: ${{ steps.auth.outputs.access_token }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
-
- - name: Check if stable image exists
- id: stable_exists
- run: |
- if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
- echo "exists=true" >> $GITHUB_OUTPUT
- fi
- if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
-
- - name: Pull build image
- run: |
- docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
- if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 'true' }}
-
- - name: Fetch Cached Artifacts
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
- if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Docker Buildx
- uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0
- if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Build Docker Image ${{ matrix.base-os }}
- uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- with:
- file: build/Dockerfile
- context: "."
- cache-from: type=gha,scope=${{ matrix.base-os }}
- target: goreleaser
- tags: "${{ matrix.image }}:${{ matrix.tag }}"
- pull: true
- load: true
- build-args: |
- BUILD_OS=${{ matrix.base-os }}
- IC_VERSION=CI
- secrets: |
- ${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
- ${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
- if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Deploy Kubernetes
- id: k8s
- run: |
- kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
- kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
- if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Install Chart
- run: >
- helm install
- ${{ matrix.type }}
- .
- --set controller.image.repository=${{ matrix.image }}
- --set controller.image.tag=${{ matrix.tag }}
- --set controller.service.type=NodePort
- --set controller.nginxplus=${{ contains(matrix.type, 'plus') && 'true' || 'false' }}
- --set controller.telemetryReporting.enable=false
- --wait
- working-directory: ${{ github.workspace }}/charts/nginx-ingress
- if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Expose Test Ingresses
- run: |
- kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
- if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Test HTTP
- run: |
- counter=0
- max_attempts=5
- until [ $(curl --write-out %{http_code} -s --output /dev/null http://localhost:8080) -eq 404 ]; do
- if [ ${counter} -eq ${max_attempts} ]; then
- exit 1
- fi
- printf '.'; counter=$(($counter+1)); sleep 5;
- done
- if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Test HTTPS
- run: |
- counter=0
- max_attempts=5
- until [ $(curl --write-out %{http_code} -ks --output /dev/null https://localhost:8443) -eq 000 ]; do
- if [ ${counter} -eq ${max_attempts} ]; then
- exit 1
- fi
- printf '.'; counter=$(($counter+1)); sleep 5;
- done
- if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- setup-matrix:
- if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
- name: Setup Matrix for Smoke Tests
- runs-on: ubuntu-22.04
- needs: [binaries, checks]
- permissions:
- contents: read
- id-token: write
- outputs:
- matrix: ${{ steps.set-matrix.outputs.matrix }}
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- - id: set-matrix
- run: |
- echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
-
- - name: Docker Buildx
- uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
-
- - name: Authenticate to Google Cloud
- id: auth
- uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
- with:
- token_format: access_token
- workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
- service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Login to GCR
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: gcr.io
- username: oauth2accesstoken
- password: ${{ steps.auth.outputs.access_token }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Check if test image exists
- id: check-image
- run: |
- docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}
- shell: bash
- continue-on-error: true
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Build Test-Runner Container
- uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- with:
- file: tests/Dockerfile
- context: "."
- cache-from: type=gha,scope=test-runner
- tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- pull: true
- push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- load: false
- if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
-
- smoke-tests:
- if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
- name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
- runs-on: ubuntu-22.04
- needs:
- - checks
- - setup-matrix
- - build-docker
- - build-docker-plus
- - build-docker-nap
- strategy:
- fail-fast: false
- matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
- permissions:
- contents: read
- id-token: write
- steps:
- - name: Checkout Repository
- uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- - name: Set image variables
- id: image_details
- run: |
- echo "name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(matrix.images.nap_modules, 'dos') && '-dos' || '' }}${{ contains(matrix.images.nap_modules, 'waf') && '-nap' || '' }}/nginx${{ contains(matrix.images.image, 'plus') && '-plus' || '' }}-ingress" >> $GITHUB_OUTPUT
- echo "build_tag=${{ needs.checks.outputs.build_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
- echo "stable_tag=${{ needs.checks.outputs.stable_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
-
- - name: Authenticate to Google Cloud
- id: auth
- uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
- with:
- token_format: access_token
- workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
- service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Login to GCR
- uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- with:
- registry: gcr.io
- username: oauth2accesstoken
- password: ${{ steps.auth.outputs.access_token }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Check if stable image exists
- id: stable_exists
- run: |
- if docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.stable_tag }}; then
- echo "exists=true" >> $GITHUB_OUTPUT
- fi
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: NAP modules
- id: nap_modules
- run: |
- [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || modules="${{ matrix.images.nap_modules }}"
- echo "modules=${modules}" >> $GITHUB_OUTPUT
- if: ${{ matrix.images.nap_modules }}
-
- - name: Pull build image
- run: |
- docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Fetch Cached Artifacts
- uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- with:
- path: ${{ github.workspace }}/dist
- key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
- fail-on-cache-miss: true
- if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Check if test image exists
- id: check-image
- run: |
- docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- shell: bash
- continue-on-error: true
- if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Build Test-Runner Container
- uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- with:
- file: tests/Dockerfile
- context: "."
- cache-from: type=gha,scope=test-runner
- tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- pull: true
- push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- load: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- if: ${{ ( needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' ) && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Build ${{ matrix.images.image }} Container
- uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- with:
- file: build/Dockerfile
- context: "."
- cache-from: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
- cache-to: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
- target: goreleaser
- tags: "${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}"
- load: true
- pull: true
- build-args: |
- BUILD_OS=${{ matrix.images.image }}
- IC_VERSION=CI
- ${{ contains(matrix.images.image, 'nap') && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
- ${{ contains(matrix.images.marker, 'appprotect') && 'DEBIAN_VERSION=buster-slim' || '' }}
- secrets: |
- ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
- ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
- ${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Run Smoke Tests
- id: smoke-tests
- uses: ./.github/actions/smoke-tests
- with:
- image-type: ${{ matrix.images.image }}
- image-name: ${{ steps.image_details.outputs.name }}
- tag: ${{ steps.image_details.outputs.build_tag }}
- marker: ${{ matrix.images.marker != '' && matrix.images.marker || '' }}
- k8s-version: ${{ matrix.k8s }}
- azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
- test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- - name: Upload Test Results
- uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
- with:
- name: ${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}
- path: ${{ github.workspace }}/tests/${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}.html
- if: always()
-
- smoke-results:
- if: ${{ always() }}
- runs-on: ubuntu-22.04
- name: Final Smoke Test Results
- needs: [smoke-tests]
- steps:
- - run: |
- result="${{ needs.smoke-tests.result }}"
- if [[ $result == "success" || $result == "skipped" ]]; then
- exit 0
- else
- exit 1
- fi
-
- tag-stable:
- name: Tag tested image as stable
- needs: [checks, smoke-results]
- permissions:
- contents: read # To checkout repository
- id-token: write # To sign into Google Container Registry
- uses: ./.github/workflows/retag-images.yml
- with:
- source_tag: ${{ needs.checks.outputs.build_tag }}
- target_tag: ${{ needs.checks.outputs.stable_tag }}
- dry_run: false
- secrets: inherit
- if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
-
- trigger-image-promotion:
- name: Promote images on Force Run
- needs:
- - build-docker
- - build-docker-plus
- - build-docker-nap
- - smoke-results
- permissions:
- contents: write # for pushing to Helm Charts repository
- id-token: write # To sign into Google Container Registry
- actions: read
- packages: write # for helm to push to GHCR
- security-events: write
- uses: ./.github/workflows/image-promotion.yml
- if: ${{ inputs.force }}
+ # build-docker-plus:
+ # name: Build Docker Plus
+ # needs: [binaries, checks]
+ # strategy:
+ # fail-fast: false
+ # matrix:
+ # image: [debian-plus, alpine-plus, alpine-plus-fips]
+ # platforms: ["linux/arm64, linux/amd64"]
+ # target: [goreleaser, aws]
+ # include:
+ # - image: ubi-plus
+ # platforms: "linux/arm64, linux/amd64, linux/s390x"
+ # target: goreleaser
+ # uses: ./.github/workflows/build-plus.yml
+ # with:
+ # platforms: ${{ matrix.platforms }}
+ # image: ${{ matrix.image }}
+ # target: ${{ matrix.target }}
+ # go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ # base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ # branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ # tag: ${{ needs.checks.outputs.build_tag }}
+ # authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ # full-build: ${{ inputs.force }}
+ # permissions:
+ # contents: read
+ # security-events: write
+ # id-token: write
+ # secrets: inherit
+
+ # build-docker-nap:
+ # name: Build Docker NAP
+ # needs: [binaries, checks]
+ # strategy:
+ # fail-fast: false
+ # matrix:
+ # image: [debian-plus-nap]
+ # platforms: ["linux/amd64"]
+ # target: [goreleaser, aws]
+ # nap_modules: [dos, waf, "waf,dos"]
+ # include:
+ # - image: ubi-9-plus-nap
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # - image: ubi-8-plus-nap
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: dos
+ # - image: ubi-8-plus-nap
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: "waf,dos"
+ # - image: ubi-9-plus-nap
+ # target: aws
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # - image: ubi-8-plus-nap
+ # target: aws
+ # platforms: "linux/amd64"
+ # nap_modules: dos
+ # - image: ubi-8-plus-nap
+ # target: aws
+ # platforms: "linux/amd64"
+ # nap_modules: "waf,dos"
+ # - image: alpine-plus-nap-fips
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # - image: alpine-plus-nap-v5-fips
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # - image: debian-plus-nap-v5
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # - image: ubi-9-plus-nap-v5
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # - image: ubi-8-plus-nap-v5
+ # target: goreleaser
+ # platforms: "linux/amd64"
+ # nap_modules: waf
+ # uses: ./.github/workflows/build-plus.yml
+ # with:
+ # platforms: ${{ matrix.platforms }}
+ # image: ${{ matrix.image }}
+ # target: ${{ matrix.target }}
+ # go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ # base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ # branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ # tag: ${{ needs.checks.outputs.build_tag }}
+ # nap-modules: ${{ matrix.nap_modules }}
+ # authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ # full-build: ${{ inputs.force }}
+ # permissions:
+ # contents: read
+ # security-events: write
+ # id-token: write
+ # secrets: inherit
+
+ # helm-tests:
+ # if: ${{ needs.checks.outputs.docs_only != 'true' }}
+ # name: Helm Tests ${{ matrix.base-os }}
+ # runs-on: ubuntu-22.04
+ # needs: [checks, binaries, build-docker, build-docker-plus]
+ # strategy:
+ # fail-fast: false
+ # matrix:
+ # include:
+ # - base-os: debian
+ # image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
+ # tag: ${{ needs.checks.outputs.build_tag }}
+ # type: oss
+ # - base-os: debian-plus
+ # image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-plus-ingress
+ # tag: ${{ needs.checks.outputs.build_tag }}
+ # type: plus
+ # permissions:
+ # contents: read
+ # id-token: write
+ # steps:
+ # - name: Checkout Repository
+ # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ # - name: Authenticate to Google Cloud
+ # id: auth
+ # uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
+ # with:
+ # token_format: access_token
+ # workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ # service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Login to GCR
+ # uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
+ # with:
+ # registry: gcr.io
+ # username: oauth2accesstoken
+ # password: ${{ steps.auth.outputs.access_token }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Check if stable image exists
+ # id: stable_exists
+ # run: |
+ # if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
+ # echo "exists=true" >> $GITHUB_OUTPUT
+ # fi
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Pull build image
+ # run: |
+ # docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
+ # if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 'true' }}
+
+ # - name: Fetch Cached Artifacts
+ # uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ # with:
+ # path: ${{ github.workspace }}/dist
+ # key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Docker Buildx
+ # uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0
+ # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Build Docker Image ${{ matrix.base-os }}
+ # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ # with:
+ # file: build/Dockerfile
+ # context: "."
+ # cache-from: type=gha,scope=${{ matrix.base-os }}
+ # target: goreleaser
+ # tags: "${{ matrix.image }}:${{ matrix.tag }}"
+ # pull: true
+ # load: true
+ # build-args: |
+ # BUILD_OS=${{ matrix.base-os }}
+ # IC_VERSION=CI
+ # secrets: |
+ # ${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
+ # ${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Deploy Kubernetes
+ # id: k8s
+ # run: |
+ # kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
+ # kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
+ # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Install Chart
+ # run: >
+ # helm install
+ # ${{ matrix.type }}
+ # .
+ # --set controller.image.repository=${{ matrix.image }}
+ # --set controller.image.tag=${{ matrix.tag }}
+ # --set controller.service.type=NodePort
+ # --set controller.nginxplus=${{ contains(matrix.type, 'plus') && 'true' || 'false' }}
+ # --set controller.telemetryReporting.enable=false
+ # --wait
+ # working-directory: ${{ github.workspace }}/charts/nginx-ingress
+ # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Expose Test Ingresses
+ # run: |
+ # kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
+ # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Test HTTP
+ # run: |
+ # counter=0
+ # max_attempts=5
+ # until [ $(curl --write-out %{http_code} -s --output /dev/null http://localhost:8080) -eq 404 ]; do
+ # if [ ${counter} -eq ${max_attempts} ]; then
+ # exit 1
+ # fi
+ # printf '.'; counter=$(($counter+1)); sleep 5;
+ # done
+ # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Test HTTPS
+ # run: |
+ # counter=0
+ # max_attempts=5
+ # until [ $(curl --write-out %{http_code} -ks --output /dev/null https://localhost:8443) -eq 000 ]; do
+ # if [ ${counter} -eq ${max_attempts} ]; then
+ # exit 1
+ # fi
+ # printf '.'; counter=$(($counter+1)); sleep 5;
+ # done
+ # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # setup-matrix:
+ # if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
+ # name: Setup Matrix for Smoke Tests
+ # runs-on: ubuntu-22.04
+ # needs: [binaries, checks]
+ # permissions:
+ # contents: read
+ # id-token: write
+ # outputs:
+ # matrix: ${{ steps.set-matrix.outputs.matrix }}
+ # steps:
+ # - name: Checkout Repository
+ # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ # - id: set-matrix
+ # run: |
+ # echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
+
+ # - name: Docker Buildx
+ # uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
+
+ # - name: Authenticate to Google Cloud
+ # id: auth
+ # uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
+ # with:
+ # token_format: access_token
+ # workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ # service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Login to GCR
+ # uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
+ # with:
+ # registry: gcr.io
+ # username: oauth2accesstoken
+ # password: ${{ steps.auth.outputs.access_token }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Check if test image exists
+ # id: check-image
+ # run: |
+ # docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}
+ # shell: bash
+ # continue-on-error: true
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Build Test-Runner Container
+ # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ # with:
+ # file: tests/Dockerfile
+ # context: "."
+ # cache-from: type=gha,scope=test-runner
+ # tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ # pull: true
+ # push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ # load: false
+ # if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
+
+ # smoke-tests:
+ # if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
+ # name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
+ # runs-on: ubuntu-22.04
+ # needs:
+ # - checks
+ # - setup-matrix
+ # - build-docker
+ # - build-docker-plus
+ # - build-docker-nap
+ # strategy:
+ # fail-fast: false
+ # matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
+ # permissions:
+ # contents: read
+ # id-token: write
+ # steps:
+ # - name: Checkout Repository
+ # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ # - name: Set image variables
+ # id: image_details
+ # run: |
+ # echo "name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(matrix.images.nap_modules, 'dos') && '-dos' || '' }}${{ contains(matrix.images.nap_modules, 'waf') && '-nap' || '' }}/nginx${{ contains(matrix.images.image, 'plus') && '-plus' || '' }}-ingress" >> $GITHUB_OUTPUT
+ # echo "build_tag=${{ needs.checks.outputs.build_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
+ # echo "stable_tag=${{ needs.checks.outputs.stable_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
+
+ # - name: Authenticate to Google Cloud
+ # id: auth
+ # uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
+ # with:
+ # token_format: access_token
+ # workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ # service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Login to GCR
+ # uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
+ # with:
+ # registry: gcr.io
+ # username: oauth2accesstoken
+ # password: ${{ steps.auth.outputs.access_token }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Check if stable image exists
+ # id: stable_exists
+ # run: |
+ # if docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.stable_tag }}; then
+ # echo "exists=true" >> $GITHUB_OUTPUT
+ # fi
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: NAP modules
+ # id: nap_modules
+ # run: |
+ # [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || modules="${{ matrix.images.nap_modules }}"
+ # echo "modules=${modules}" >> $GITHUB_OUTPUT
+ # if: ${{ matrix.images.nap_modules }}
+
+ # - name: Pull build image
+ # run: |
+ # docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Fetch Cached Artifacts
+ # uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ # with:
+ # path: ${{ github.workspace }}/dist
+ # key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
+ # fail-on-cache-miss: true
+ # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Check if test image exists
+ # id: check-image
+ # run: |
+ # docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ # shell: bash
+ # continue-on-error: true
+ # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Build Test-Runner Container
+ # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ # with:
+ # file: tests/Dockerfile
+ # context: "."
+ # cache-from: type=gha,scope=test-runner
+ # tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ # pull: true
+ # push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ # load: ${{ needs.checks.outputs.forked_workflow == 'true' }}
+ # if: ${{ ( needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' ) && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Build ${{ matrix.images.image }} Container
+ # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ # with:
+ # file: build/Dockerfile
+ # context: "."
+ # cache-from: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
+ # cache-to: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
+ # target: goreleaser
+ # tags: "${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}"
+ # load: true
+ # pull: true
+ # build-args: |
+ # BUILD_OS=${{ matrix.images.image }}
+ # IC_VERSION=CI
+ # ${{ contains(matrix.images.image, 'nap') && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
+ # ${{ contains(matrix.images.marker, 'appprotect') && 'DEBIAN_VERSION=buster-slim' || '' }}
+ # secrets: |
+ # ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
+ # ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
+ # ${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
+ # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Run Smoke Tests
+ # id: smoke-tests
+ # uses: ./.github/actions/smoke-tests
+ # with:
+ # image-type: ${{ matrix.images.image }}
+ # image-name: ${{ steps.image_details.outputs.name }}
+ # tag: ${{ steps.image_details.outputs.build_tag }}
+ # marker: ${{ matrix.images.marker != '' && matrix.images.marker || '' }}
+ # k8s-version: ${{ matrix.k8s }}
+ # azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
+ # test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ # - name: Upload Test Results
+ # uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ # with:
+ # name: ${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}
+ # path: ${{ github.workspace }}/tests/${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}.html
+ # if: always()
+
+ # smoke-results:
+ # if: ${{ always() }}
+ # runs-on: ubuntu-22.04
+ # name: Final Smoke Test Results
+ # needs: [smoke-tests]
+ # steps:
+ # - run: |
+ # result="${{ needs.smoke-tests.result }}"
+ # if [[ $result == "success" || $result == "skipped" ]]; then
+ # exit 0
+ # else
+ # exit 1
+ # fi
+
+ # tag-stable:
+ # name: Tag tested image as stable
+ # needs: [checks, smoke-results]
+ # permissions:
+ # contents: read # To checkout repository
+ # id-token: write # To sign into Google Container Registry
+ # uses: ./.github/workflows/retag-images.yml
+ # with:
+ # source_tag: ${{ needs.checks.outputs.build_tag }}
+ # target_tag: ${{ needs.checks.outputs.stable_tag }}
+ # dry_run: false
+ # secrets: inherit
+ # if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
+
+ # trigger-image-promotion:
+ # name: Promote images on Force Run
+ # needs:
+ # - build-docker
+ # - build-docker-plus
+ # - build-docker-nap
+ # - smoke-results
+ # permissions:
+ # contents: write # for pushing to Helm Charts repository
+ # id-token: write # To sign into Google Container Registry
+ # actions: read
+ # packages: write # for helm to push to GHCR
+ # security-events: write
+ # uses: ./.github/workflows/image-promotion.yml
+ # if: ${{ inputs.force }}
From f8aa05d7af17a539ddd4a48595624dc55fe3e594 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:40:41 +0100
Subject: [PATCH 26/38] switch input to boolean
---
.github/workflows/ci.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f0069a5204..41c06e7034 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -9,9 +9,10 @@ on:
workflow_dispatch:
inputs:
force:
+ type: boolean
description: "Force rebuild"
required: false
- default: "false"
+ default: false
defaults:
run:
From 18e93b245ad9f37f35331fdeceb9b8e76b570799 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:45:48 +0100
Subject: [PATCH 27/38] ensure full-build is always a bool
---
.github/workflows/ci.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 41c06e7034..6dc8f8a1e3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -294,7 +294,7 @@ jobs:
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- full-build: ${{ inputs.force }}
+ full-build: ${{ inputs.force && inputs.force || false }}
tag: ${{ needs.checks.outputs.build_tag }}
branch: ${{ github.head_ref && github.head_ref || github.ref }}
permissions:
@@ -328,7 +328,7 @@ jobs:
# branch: ${{ github.head_ref && github.head_ref || github.ref }}
# tag: ${{ needs.checks.outputs.build_tag }}
# authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- # full-build: ${{ inputs.force }}
+ # full-build: ${{ inputs.force && inputs.force || false }}
# permissions:
# contents: read
# security-events: write
@@ -401,7 +401,7 @@ jobs:
# tag: ${{ needs.checks.outputs.build_tag }}
# nap-modules: ${{ matrix.nap_modules }}
# authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- # full-build: ${{ inputs.force }}
+ # full-build: ${{ inputs.force && inputs.force || false }}
# permissions:
# contents: read
# security-events: write
From 039c4fc0b941c9d33166d5a4707b8a699ac76e33 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:48:13 +0100
Subject: [PATCH 28/38] uncomment disabled jobs
---
.github/workflows/ci.yml | 1014 +++++++++++++++++++-------------------
1 file changed, 507 insertions(+), 507 deletions(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6dc8f8a1e3..35828f97a8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -192,42 +192,42 @@ jobs:
token: ${{ secrets.CODECOV_TOKEN }} # required
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- # release-notes:
- # name: Release Notes
- # runs-on: ubuntu-22.04
- # needs: [checks, unit-tests]
- # outputs:
- # release-url: ${{ steps.release-notes.outputs.release-url }}
- # permissions:
- # contents: write # for lucacome/draft-release
- # steps:
- # - name: Checkout Repository
- # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
- # with:
- # fetch-depth: 0
-
- # - name: Create/Update Draft
- # uses: lucacome/draft-release@8a63d32c79a171ae6048e614a8988f0ac3ed56d4 # v1.1.0
- # id: release-notes
- # with:
- # minor-label: "enhancement"
- # major-label: "change"
- # publish: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
- # collapse-after: 50
- # variables: |
- # helm-chart=${{ needs.checks.outputs.chart_version }}
- # notes-footer: |
- # ## Upgrade
- # - For NGINX, use the {{version}} images from our [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/tags?page=1&ordering=last_updated&name={{version-number}}), [GitHub Container](https://github.com/nginxinc/kubernetes-ingress/pkgs/container/kubernetes-ingress), [Amazon ECR Public Gallery](https://gallery.ecr.aws/nginx/nginx-ingress) or [Quay.io](https://quay.io/repository/nginx/nginx-ingress).
- # - For NGINX Plus, use the {{version}} images from the F5 Container registry, the [AWS Marketplace](https://aws.amazon.com/marketplace/search/?CREATOR=741df81b-dfdc-4d36-b8da-945ea66b522c&FULFILLMENT_OPTION_TYPE=CONTAINER&filters=CREATOR%2CFULFILLMENT_OPTION_TYPE), the [GCP Marketplace](https://console.cloud.google.com/marketplace/browse?filter=partner:F5,%20Inc.&filter=solution-type:k8s&filter=category:networking) or build your own image using the {{version}} source code.
- # - For Helm, use version {{helm-chart}} of the chart.
-
- # ## Resources
- # - Documentation -- https://docs.nginx.com/nginx-ingress-controller/
- # - Configuration examples -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/examples
- # - Helm Chart -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/charts/nginx-ingress
- # - Operator -- https://github.com/nginxinc/nginx-ingress-helm-operator
- # if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
+ release-notes:
+ name: Release Notes
+ runs-on: ubuntu-22.04
+ needs: [checks, unit-tests]
+ outputs:
+ release-url: ${{ steps.release-notes.outputs.release-url }}
+ permissions:
+ contents: write # for lucacome/draft-release
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+ with:
+ fetch-depth: 0
+
+ - name: Create/Update Draft
+ uses: lucacome/draft-release@8a63d32c79a171ae6048e614a8988f0ac3ed56d4 # v1.1.0
+ id: release-notes
+ with:
+ minor-label: "enhancement"
+ major-label: "change"
+ publish: ${{ github.ref_type == 'tag' && vars.OLD_RELEASE_FLOW == 'true' }}
+ collapse-after: 50
+ variables: |
+ helm-chart=${{ needs.checks.outputs.chart_version }}
+ notes-footer: |
+ ## Upgrade
+ - For NGINX, use the {{version}} images from our [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/tags?page=1&ordering=last_updated&name={{version-number}}), [GitHub Container](https://github.com/nginxinc/kubernetes-ingress/pkgs/container/kubernetes-ingress), [Amazon ECR Public Gallery](https://gallery.ecr.aws/nginx/nginx-ingress) or [Quay.io](https://quay.io/repository/nginx/nginx-ingress).
+ - For NGINX Plus, use the {{version}} images from the F5 Container registry, the [AWS Marketplace](https://aws.amazon.com/marketplace/search/?CREATOR=741df81b-dfdc-4d36-b8da-945ea66b522c&FULFILLMENT_OPTION_TYPE=CONTAINER&filters=CREATOR%2CFULFILLMENT_OPTION_TYPE), the [GCP Marketplace](https://console.cloud.google.com/marketplace/browse?filter=partner:F5,%20Inc.&filter=solution-type:k8s&filter=category:networking) or build your own image using the {{version}} source code.
+ - For Helm, use version {{helm-chart}} of the chart.
+
+ ## Resources
+ - Documentation -- https://docs.nginx.com/nginx-ingress-controller/
+ - Configuration examples -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/examples
+ - Helm Chart -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/charts/nginx-ingress
+ - Operator -- https://github.com/nginxinc/nginx-ingress-helm-operator
+ if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
binaries:
name: Build Binaries
@@ -305,474 +305,474 @@ jobs:
packages: write
secrets: inherit
- # build-docker-plus:
- # name: Build Docker Plus
- # needs: [binaries, checks]
- # strategy:
- # fail-fast: false
- # matrix:
- # image: [debian-plus, alpine-plus, alpine-plus-fips]
- # platforms: ["linux/arm64, linux/amd64"]
- # target: [goreleaser, aws]
- # include:
- # - image: ubi-plus
- # platforms: "linux/arm64, linux/amd64, linux/s390x"
- # target: goreleaser
- # uses: ./.github/workflows/build-plus.yml
- # with:
- # platforms: ${{ matrix.platforms }}
- # image: ${{ matrix.image }}
- # target: ${{ matrix.target }}
- # go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- # base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- # branch: ${{ github.head_ref && github.head_ref || github.ref }}
- # tag: ${{ needs.checks.outputs.build_tag }}
- # authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- # full-build: ${{ inputs.force && inputs.force || false }}
- # permissions:
- # contents: read
- # security-events: write
- # id-token: write
- # secrets: inherit
-
- # build-docker-nap:
- # name: Build Docker NAP
- # needs: [binaries, checks]
- # strategy:
- # fail-fast: false
- # matrix:
- # image: [debian-plus-nap]
- # platforms: ["linux/amd64"]
- # target: [goreleaser, aws]
- # nap_modules: [dos, waf, "waf,dos"]
- # include:
- # - image: ubi-9-plus-nap
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: waf
- # - image: ubi-8-plus-nap
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: dos
- # - image: ubi-8-plus-nap
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: "waf,dos"
- # - image: ubi-9-plus-nap
- # target: aws
- # platforms: "linux/amd64"
- # nap_modules: waf
- # - image: ubi-8-plus-nap
- # target: aws
- # platforms: "linux/amd64"
- # nap_modules: dos
- # - image: ubi-8-plus-nap
- # target: aws
- # platforms: "linux/amd64"
- # nap_modules: "waf,dos"
- # - image: alpine-plus-nap-fips
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: waf
- # - image: alpine-plus-nap-v5-fips
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: waf
- # - image: debian-plus-nap-v5
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: waf
- # - image: ubi-9-plus-nap-v5
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: waf
- # - image: ubi-8-plus-nap-v5
- # target: goreleaser
- # platforms: "linux/amd64"
- # nap_modules: waf
- # uses: ./.github/workflows/build-plus.yml
- # with:
- # platforms: ${{ matrix.platforms }}
- # image: ${{ matrix.image }}
- # target: ${{ matrix.target }}
- # go-md5: ${{ needs.checks.outputs.go_code_md5 }}
- # base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
- # branch: ${{ github.head_ref && github.head_ref || github.ref }}
- # tag: ${{ needs.checks.outputs.build_tag }}
- # nap-modules: ${{ matrix.nap_modules }}
- # authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
- # full-build: ${{ inputs.force && inputs.force || false }}
- # permissions:
- # contents: read
- # security-events: write
- # id-token: write
- # secrets: inherit
-
- # helm-tests:
- # if: ${{ needs.checks.outputs.docs_only != 'true' }}
- # name: Helm Tests ${{ matrix.base-os }}
- # runs-on: ubuntu-22.04
- # needs: [checks, binaries, build-docker, build-docker-plus]
- # strategy:
- # fail-fast: false
- # matrix:
- # include:
- # - base-os: debian
- # image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
- # tag: ${{ needs.checks.outputs.build_tag }}
- # type: oss
- # - base-os: debian-plus
- # image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-plus-ingress
- # tag: ${{ needs.checks.outputs.build_tag }}
- # type: plus
- # permissions:
- # contents: read
- # id-token: write
- # steps:
- # - name: Checkout Repository
- # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- # - name: Authenticate to Google Cloud
- # id: auth
- # uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
- # with:
- # token_format: access_token
- # workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
- # service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Login to GCR
- # uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- # with:
- # registry: gcr.io
- # username: oauth2accesstoken
- # password: ${{ steps.auth.outputs.access_token }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Check if stable image exists
- # id: stable_exists
- # run: |
- # if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
- # echo "exists=true" >> $GITHUB_OUTPUT
- # fi
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Pull build image
- # run: |
- # docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
- # if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 'true' }}
-
- # - name: Fetch Cached Artifacts
- # uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- # with:
- # path: ${{ github.workspace }}/dist
- # key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Docker Buildx
- # uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0
- # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Build Docker Image ${{ matrix.base-os }}
- # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- # with:
- # file: build/Dockerfile
- # context: "."
- # cache-from: type=gha,scope=${{ matrix.base-os }}
- # target: goreleaser
- # tags: "${{ matrix.image }}:${{ matrix.tag }}"
- # pull: true
- # load: true
- # build-args: |
- # BUILD_OS=${{ matrix.base-os }}
- # IC_VERSION=CI
- # secrets: |
- # ${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
- # ${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Deploy Kubernetes
- # id: k8s
- # run: |
- # kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
- # kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
- # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Install Chart
- # run: >
- # helm install
- # ${{ matrix.type }}
- # .
- # --set controller.image.repository=${{ matrix.image }}
- # --set controller.image.tag=${{ matrix.tag }}
- # --set controller.service.type=NodePort
- # --set controller.nginxplus=${{ contains(matrix.type, 'plus') && 'true' || 'false' }}
- # --set controller.telemetryReporting.enable=false
- # --wait
- # working-directory: ${{ github.workspace }}/charts/nginx-ingress
- # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Expose Test Ingresses
- # run: |
- # kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
- # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Test HTTP
- # run: |
- # counter=0
- # max_attempts=5
- # until [ $(curl --write-out %{http_code} -s --output /dev/null http://localhost:8080) -eq 404 ]; do
- # if [ ${counter} -eq ${max_attempts} ]; then
- # exit 1
- # fi
- # printf '.'; counter=$(($counter+1)); sleep 5;
- # done
- # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Test HTTPS
- # run: |
- # counter=0
- # max_attempts=5
- # until [ $(curl --write-out %{http_code} -ks --output /dev/null https://localhost:8443) -eq 000 ]; do
- # if [ ${counter} -eq ${max_attempts} ]; then
- # exit 1
- # fi
- # printf '.'; counter=$(($counter+1)); sleep 5;
- # done
- # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # setup-matrix:
- # if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
- # name: Setup Matrix for Smoke Tests
- # runs-on: ubuntu-22.04
- # needs: [binaries, checks]
- # permissions:
- # contents: read
- # id-token: write
- # outputs:
- # matrix: ${{ steps.set-matrix.outputs.matrix }}
- # steps:
- # - name: Checkout Repository
- # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- # - id: set-matrix
- # run: |
- # echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
-
- # - name: Docker Buildx
- # uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
-
- # - name: Authenticate to Google Cloud
- # id: auth
- # uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
- # with:
- # token_format: access_token
- # workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
- # service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Login to GCR
- # uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- # with:
- # registry: gcr.io
- # username: oauth2accesstoken
- # password: ${{ steps.auth.outputs.access_token }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Check if test image exists
- # id: check-image
- # run: |
- # docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}
- # shell: bash
- # continue-on-error: true
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Build Test-Runner Container
- # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- # with:
- # file: tests/Dockerfile
- # context: "."
- # cache-from: type=gha,scope=test-runner
- # tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- # pull: true
- # push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- # load: false
- # if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
-
- # smoke-tests:
- # if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
- # name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
- # runs-on: ubuntu-22.04
- # needs:
- # - checks
- # - setup-matrix
- # - build-docker
- # - build-docker-plus
- # - build-docker-nap
- # strategy:
- # fail-fast: false
- # matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
- # permissions:
- # contents: read
- # id-token: write
- # steps:
- # - name: Checkout Repository
- # uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
-
- # - name: Set image variables
- # id: image_details
- # run: |
- # echo "name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(matrix.images.nap_modules, 'dos') && '-dos' || '' }}${{ contains(matrix.images.nap_modules, 'waf') && '-nap' || '' }}/nginx${{ contains(matrix.images.image, 'plus') && '-plus' || '' }}-ingress" >> $GITHUB_OUTPUT
- # echo "build_tag=${{ needs.checks.outputs.build_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
- # echo "stable_tag=${{ needs.checks.outputs.stable_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
-
- # - name: Authenticate to Google Cloud
- # id: auth
- # uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
- # with:
- # token_format: access_token
- # workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
- # service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Login to GCR
- # uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
- # with:
- # registry: gcr.io
- # username: oauth2accesstoken
- # password: ${{ steps.auth.outputs.access_token }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Check if stable image exists
- # id: stable_exists
- # run: |
- # if docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.stable_tag }}; then
- # echo "exists=true" >> $GITHUB_OUTPUT
- # fi
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: NAP modules
- # id: nap_modules
- # run: |
- # [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || modules="${{ matrix.images.nap_modules }}"
- # echo "modules=${modules}" >> $GITHUB_OUTPUT
- # if: ${{ matrix.images.nap_modules }}
-
- # - name: Pull build image
- # run: |
- # docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Fetch Cached Artifacts
- # uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
- # with:
- # path: ${{ github.workspace }}/dist
- # key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
- # fail-on-cache-miss: true
- # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Check if test image exists
- # id: check-image
- # run: |
- # docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- # shell: bash
- # continue-on-error: true
- # if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Build Test-Runner Container
- # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- # with:
- # file: tests/Dockerfile
- # context: "."
- # cache-from: type=gha,scope=test-runner
- # tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- # pull: true
- # push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- # load: ${{ needs.checks.outputs.forked_workflow == 'true' }}
- # if: ${{ ( needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' ) && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Build ${{ matrix.images.image }} Container
- # uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
- # with:
- # file: build/Dockerfile
- # context: "."
- # cache-from: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
- # cache-to: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
- # target: goreleaser
- # tags: "${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}"
- # load: true
- # pull: true
- # build-args: |
- # BUILD_OS=${{ matrix.images.image }}
- # IC_VERSION=CI
- # ${{ contains(matrix.images.image, 'nap') && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
- # ${{ contains(matrix.images.marker, 'appprotect') && 'DEBIAN_VERSION=buster-slim' || '' }}
- # secrets: |
- # ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
- # ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
- # ${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- # if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Run Smoke Tests
- # id: smoke-tests
- # uses: ./.github/actions/smoke-tests
- # with:
- # image-type: ${{ matrix.images.image }}
- # image-name: ${{ steps.image_details.outputs.name }}
- # tag: ${{ steps.image_details.outputs.build_tag }}
- # marker: ${{ matrix.images.marker != '' && matrix.images.marker || '' }}
- # k8s-version: ${{ matrix.k8s }}
- # azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
- # test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- # if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
-
- # - name: Upload Test Results
- # uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
- # with:
- # name: ${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}
- # path: ${{ github.workspace }}/tests/${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}.html
- # if: always()
-
- # smoke-results:
- # if: ${{ always() }}
- # runs-on: ubuntu-22.04
- # name: Final Smoke Test Results
- # needs: [smoke-tests]
- # steps:
- # - run: |
- # result="${{ needs.smoke-tests.result }}"
- # if [[ $result == "success" || $result == "skipped" ]]; then
- # exit 0
- # else
- # exit 1
- # fi
-
- # tag-stable:
- # name: Tag tested image as stable
- # needs: [checks, smoke-results]
- # permissions:
- # contents: read # To checkout repository
- # id-token: write # To sign into Google Container Registry
- # uses: ./.github/workflows/retag-images.yml
- # with:
- # source_tag: ${{ needs.checks.outputs.build_tag }}
- # target_tag: ${{ needs.checks.outputs.stable_tag }}
- # dry_run: false
- # secrets: inherit
- # if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
-
- # trigger-image-promotion:
- # name: Promote images on Force Run
- # needs:
- # - build-docker
- # - build-docker-plus
- # - build-docker-nap
- # - smoke-results
- # permissions:
- # contents: write # for pushing to Helm Charts repository
- # id-token: write # To sign into Google Container Registry
- # actions: read
- # packages: write # for helm to push to GHCR
- # security-events: write
- # uses: ./.github/workflows/image-promotion.yml
- # if: ${{ inputs.force }}
+ build-docker-plus:
+ name: Build Docker Plus
+ needs: [binaries, checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian-plus, alpine-plus, alpine-plus-fips]
+ platforms: ["linux/arm64, linux/amd64"]
+ target: [goreleaser, aws]
+ include:
+ - image: ubi-plus
+ platforms: "linux/arm64, linux/amd64, linux/s390x"
+ target: goreleaser
+ uses: ./.github/workflows/build-plus.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ target: ${{ matrix.target }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ tag: ${{ needs.checks.outputs.build_tag }}
+ authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ full-build: ${{ inputs.force && inputs.force || false }}
+ permissions:
+ contents: read
+ security-events: write
+ id-token: write
+ secrets: inherit
+
+ build-docker-nap:
+ name: Build Docker NAP
+ needs: [binaries, checks]
+ strategy:
+ fail-fast: false
+ matrix:
+ image: [debian-plus-nap]
+ platforms: ["linux/amd64"]
+ target: [goreleaser, aws]
+ nap_modules: [dos, waf, "waf,dos"]
+ include:
+ - image: ubi-9-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: dos
+ - image: ubi-8-plus-nap
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: "waf,dos"
+ - image: ubi-9-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: dos
+ - image: ubi-8-plus-nap
+ target: aws
+ platforms: "linux/amd64"
+ nap_modules: "waf,dos"
+ - image: alpine-plus-nap-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: alpine-plus-nap-v5-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: debian-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-9-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ uses: ./.github/workflows/build-plus.yml
+ with:
+ platforms: ${{ matrix.platforms }}
+ image: ${{ matrix.image }}
+ target: ${{ matrix.target }}
+ go-md5: ${{ needs.checks.outputs.go_code_md5 }}
+ base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
+ branch: ${{ github.head_ref && github.head_ref || github.ref }}
+ tag: ${{ needs.checks.outputs.build_tag }}
+ nap-modules: ${{ matrix.nap_modules }}
+ authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
+ full-build: ${{ inputs.force && inputs.force || false }}
+ permissions:
+ contents: read
+ security-events: write
+ id-token: write
+ secrets: inherit
+
+ helm-tests:
+ if: ${{ needs.checks.outputs.docs_only != 'true' }}
+ name: Helm Tests ${{ matrix.base-os }}
+ runs-on: ubuntu-22.04
+ needs: [checks, binaries, build-docker, build-docker-plus]
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - base-os: debian
+ image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
+ tag: ${{ needs.checks.outputs.build_tag }}
+ type: oss
+ - base-os: debian-plus
+ image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-plus-ingress
+ tag: ${{ needs.checks.outputs.build_tag }}
+ type: plus
+ permissions:
+ contents: read
+ id-token: write
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ - name: Authenticate to Google Cloud
+ id: auth
+ uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
+ with:
+ token_format: access_token
+ workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Login to GCR
+ uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
+ with:
+ registry: gcr.io
+ username: oauth2accesstoken
+ password: ${{ steps.auth.outputs.access_token }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Check if stable image exists
+ id: stable_exists
+ run: |
+ if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
+ echo "exists=true" >> $GITHUB_OUTPUT
+ fi
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Pull build image
+ run: |
+ docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
+ if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 'true' }}
+
+ - name: Fetch Cached Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Docker Buildx
+ uses: docker/setup-buildx-action@2b51285047da1547ffb1b2203d8be4c0af6b1f20 # v3.2.0
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Build Docker Image ${{ matrix.base-os }}
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ with:
+ file: build/Dockerfile
+ context: "."
+ cache-from: type=gha,scope=${{ matrix.base-os }}
+ target: goreleaser
+ tags: "${{ matrix.image }}:${{ matrix.tag }}"
+ pull: true
+ load: true
+ build-args: |
+ BUILD_OS=${{ matrix.base-os }}
+ IC_VERSION=CI
+ secrets: |
+ ${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
+ ${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Deploy Kubernetes
+ id: k8s
+ run: |
+ kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
+ kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Install Chart
+ run: >
+ helm install
+ ${{ matrix.type }}
+ .
+ --set controller.image.repository=${{ matrix.image }}
+ --set controller.image.tag=${{ matrix.tag }}
+ --set controller.service.type=NodePort
+ --set controller.nginxplus=${{ contains(matrix.type, 'plus') && 'true' || 'false' }}
+ --set controller.telemetryReporting.enable=false
+ --wait
+ working-directory: ${{ github.workspace }}/charts/nginx-ingress
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Expose Test Ingresses
+ run: |
+ kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Test HTTP
+ run: |
+ counter=0
+ max_attempts=5
+ until [ $(curl --write-out %{http_code} -s --output /dev/null http://localhost:8080) -eq 404 ]; do
+ if [ ${counter} -eq ${max_attempts} ]; then
+ exit 1
+ fi
+ printf '.'; counter=$(($counter+1)); sleep 5;
+ done
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Test HTTPS
+ run: |
+ counter=0
+ max_attempts=5
+ until [ $(curl --write-out %{http_code} -ks --output /dev/null https://localhost:8443) -eq 000 ]; do
+ if [ ${counter} -eq ${max_attempts} ]; then
+ exit 1
+ fi
+ printf '.'; counter=$(($counter+1)); sleep 5;
+ done
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ setup-matrix:
+ if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
+ name: Setup Matrix for Smoke Tests
+ runs-on: ubuntu-22.04
+ needs: [binaries, checks]
+ permissions:
+ contents: read
+ id-token: write
+ outputs:
+ matrix: ${{ steps.set-matrix.outputs.matrix }}
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ - id: set-matrix
+ run: |
+ echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
+
+ - name: Docker Buildx
+ uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
+
+ - name: Authenticate to Google Cloud
+ id: auth
+ uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
+ with:
+ token_format: access_token
+ workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Login to GCR
+ uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
+ with:
+ registry: gcr.io
+ username: oauth2accesstoken
+ password: ${{ steps.auth.outputs.access_token }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Check if test image exists
+ id: check-image
+ run: |
+ docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}
+ shell: bash
+ continue-on-error: true
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Build Test-Runner Container
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ with:
+ file: tests/Dockerfile
+ context: "."
+ cache-from: type=gha,scope=test-runner
+ tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ pull: true
+ push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ load: false
+ if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
+
+ smoke-tests:
+ if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
+ name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
+ runs-on: ubuntu-22.04
+ needs:
+ - checks
+ - setup-matrix
+ - build-docker
+ - build-docker-plus
+ - build-docker-nap
+ strategy:
+ fail-fast: false
+ matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
+ permissions:
+ contents: read
+ id-token: write
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
+
+ - name: Set image variables
+ id: image_details
+ run: |
+ echo "name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(matrix.images.nap_modules, 'dos') && '-dos' || '' }}${{ contains(matrix.images.nap_modules, 'waf') && '-nap' || '' }}/nginx${{ contains(matrix.images.image, 'plus') && '-plus' || '' }}-ingress" >> $GITHUB_OUTPUT
+ echo "build_tag=${{ needs.checks.outputs.build_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
+ echo "stable_tag=${{ needs.checks.outputs.stable_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
+
+ - name: Authenticate to Google Cloud
+ id: auth
+ uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3
+ with:
+ token_format: access_token
+ workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
+ service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Login to GCR
+ uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0
+ with:
+ registry: gcr.io
+ username: oauth2accesstoken
+ password: ${{ steps.auth.outputs.access_token }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Check if stable image exists
+ id: stable_exists
+ run: |
+ if docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.stable_tag }}; then
+ echo "exists=true" >> $GITHUB_OUTPUT
+ fi
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: NAP modules
+ id: nap_modules
+ run: |
+ [[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || modules="${{ matrix.images.nap_modules }}"
+ echo "modules=${modules}" >> $GITHUB_OUTPUT
+ if: ${{ matrix.images.nap_modules }}
+
+ - name: Pull build image
+ run: |
+ docker pull ${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Fetch Cached Artifacts
+ uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
+ fail-on-cache-miss: true
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Check if test image exists
+ id: check-image
+ run: |
+ docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ shell: bash
+ continue-on-error: true
+ if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Build Test-Runner Container
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ with:
+ file: tests/Dockerfile
+ context: "."
+ cache-from: type=gha,scope=test-runner
+ tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ pull: true
+ push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
+ load: ${{ needs.checks.outputs.forked_workflow == 'true' }}
+ if: ${{ ( needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' ) && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Build ${{ matrix.images.image }} Container
+ uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
+ with:
+ file: build/Dockerfile
+ context: "."
+ cache-from: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
+ cache-to: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
+ target: goreleaser
+ tags: "${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}"
+ load: true
+ pull: true
+ build-args: |
+ BUILD_OS=${{ matrix.images.image }}
+ IC_VERSION=CI
+ ${{ contains(matrix.images.image, 'nap') && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
+ ${{ contains(matrix.images.marker, 'appprotect') && 'DEBIAN_VERSION=buster-slim' || '' }}
+ secrets: |
+ ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
+ ${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
+ ${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
+ if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Run Smoke Tests
+ id: smoke-tests
+ uses: ./.github/actions/smoke-tests
+ with:
+ image-type: ${{ matrix.images.image }}
+ image-name: ${{ steps.image_details.outputs.name }}
+ tag: ${{ steps.image_details.outputs.build_tag }}
+ marker: ${{ matrix.images.marker != '' && matrix.images.marker || '' }}
+ k8s-version: ${{ matrix.k8s }}
+ azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
+ test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
+ if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
+
+ - name: Upload Test Results
+ uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
+ with:
+ name: ${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}
+ path: ${{ github.workspace }}/tests/${{ steps.smoke-tests.outputs.test-results-name }}-${{ matrix.k8s }}.html
+ if: always()
+
+ smoke-results:
+ if: ${{ always() }}
+ runs-on: ubuntu-22.04
+ name: Final Smoke Test Results
+ needs: [smoke-tests]
+ steps:
+ - run: |
+ result="${{ needs.smoke-tests.result }}"
+ if [[ $result == "success" || $result == "skipped" ]]; then
+ exit 0
+ else
+ exit 1
+ fi
+
+ tag-stable:
+ name: Tag tested image as stable
+ needs: [checks, smoke-results]
+ permissions:
+ contents: read # To checkout repository
+ id-token: write # To sign into Google Container Registry
+ uses: ./.github/workflows/retag-images.yml
+ with:
+ source_tag: ${{ needs.checks.outputs.build_tag }}
+ target_tag: ${{ needs.checks.outputs.stable_tag }}
+ dry_run: false
+ secrets: inherit
+ if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'false' && needs.smoke-results.result == 'success' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
+
+ trigger-image-promotion:
+ name: Promote images on Force Run
+ needs:
+ - build-docker
+ - build-docker-plus
+ - build-docker-nap
+ - smoke-results
+ permissions:
+ contents: write # for pushing to Helm Charts repository
+ id-token: write # To sign into Google Container Registry
+ actions: read
+ packages: write # for helm to push to GHCR
+ security-events: write
+ uses: ./.github/workflows/image-promotion.yml
+ if: ${{ inputs.force }}
From 39bf7c14c36586fa72b46dc04e89240655a14cb3 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:52:32 +0100
Subject: [PATCH 29/38] fully validate source branch string
---
.github/workflows/update-docker-sha.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/update-docker-sha.yml b/.github/workflows/update-docker-sha.yml
index 7d08b9a74f..603c2afd15 100644
--- a/.github/workflows/update-docker-sha.yml
+++ b/.github/workflows/update-docker-sha.yml
@@ -37,7 +37,7 @@ jobs:
id: vars
run: |
source_branch=main
- if ${{ inputs.source_branch }}; then
+ if [ -n "${{ inputs.source_branch }}" ]; then
source_branch=${{ inputs.source_branch }}
fi
echo "source_branch=${source_branch}" >> $GITHUB_OUTPUT
From d77bb657b6d78c6065eb4ac2dac81ae1d7f13a58 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 11:53:22 +0100
Subject: [PATCH 30/38] ensure boolean logic for "force" variable in image
promotion workflow
---
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 35828f97a8..fe123a6931 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -775,4 +775,4 @@ jobs:
packages: write # for helm to push to GHCR
security-events: write
uses: ./.github/workflows/image-promotion.yml
- if: ${{ inputs.force }}
+ if: ${{ inputs.force && inputs.force || false }}
From a422598b5ed48997a38a8d380c3cc306af2578aa Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 12:07:30 +0100
Subject: [PATCH 31/38] fix setcap prebuild not working
---
build/Dockerfile | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/build/Dockerfile b/build/Dockerfile
index 0892f73be4..133a6c2eaa 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -667,6 +667,7 @@ USER 101
############################################# Builder style stage to avoid duplicate layers for ingress and ingress with setcap #############################################
+# Builder image for goreleaser
FROM common AS goreleaser-setcap
ARG TARGETARCH
@@ -684,13 +685,23 @@ LABEL org.nginx.kic.image.build.version="goreleaser"
COPY --link --chown=101:0 --from=goreleaser-setcap /nginx-ingress /
+############################################# Builder style stage to avoid duplicate layers for ingress and ingress with setcap #############################################
+# Builder image for goreleaser-prebuilt
+FROM ${PREBUILT_BASE_IMG} AS goreleaser-setcap-prebuilt
+ARG TARGETARCH
+
+COPY --link --chown=101:0 dist/kubernetes-ingress_linux_${TARGETARCH}*/nginx-ingress /
+USER 0
+RUN setcap 'cap_net_bind_service=+ep' /nginx-ingress && setcap -v 'cap_net_bind_service=+ep' /nginx-ingress
+
+
############################################# Create image with nginx-ingress built by GoReleaser & using prebuilt base image #############################################
FROM ${PREBUILT_BASE_IMG} AS goreleaser-prebuilt
ARG TARGETARCH
LABEL org.nginx.kic.image.build.version="goreleaser"
-COPY --link --chown=101:0 --from=goreleaser-setcap /nginx-ingress /
+COPY --link --chown=101:0 --from=goreleaser-setcap-prebuilt /nginx-ingress /
# root is required for `setcap` invocation
USER 0
RUN --mount=type=bind,target=/tmp [ -z "${BUILD_OS##*plus*}" ] && PLUS=-plus; cp -a /tmp/internal/configs/version1/nginx$PLUS.ingress.tmpl /tmp/internal/configs/version1/nginx$PLUS.tmpl \
@@ -701,6 +712,7 @@ USER 101
############################################# Builder style stage to avoid duplicate layers for ingress and ingress with setcap #############################################
+# Builder image for aws
FROM common AS aws-setcap
ARG TARGETARCH
ARG NAP_MODULES_AWS
@@ -720,6 +732,17 @@ LABEL org.nginx.kic.image.build.version="aws"
COPY --link --chown=101:0 --from=aws-setcap /nginx-ingress /
+############################################# Builder style stage to avoid duplicate layers for ingress and ingress with setcap #############################################
+# Builder image for aws-prebuilt
+FROM ${PREBUILT_BASE_IMG} AS aws-setcap-prebuilt
+ARG TARGETARCH
+ARG NAP_MODULES_AWS
+
+COPY --link --chown=101:0 dist/aws*${NAP_MODULES_AWS}_linux_${TARGETARCH}*/nginx-ingress /
+USER 0
+RUN setcap 'cap_net_bind_service=+ep' /nginx-ingress && setcap -v 'cap_net_bind_service=+ep' /nginx-ingress
+
+
############################################# Create image with nginx-ingress built by GoReleaser for AWS Marketplace #############################################
FROM ${PREBUILT_BASE_IMG} AS aws-prebuilt
ARG TARGETARCH
@@ -727,7 +750,7 @@ ARG NAP_MODULES_AWS
LABEL org.nginx.kic.image.build.version="aws"
-COPY --link --chown=101:0 --from=aws-setcap /nginx-ingress /
+COPY --link --chown=101:0 --from=aws-setcap-prebuilt /nginx-ingress /
USER 0
RUN --mount=type=bind,target=/tmp [ -z "${BUILD_OS##*plus*}" ] && PLUS=-plus; cp -a /tmp/internal/configs/version1/nginx$PLUS.ingress.tmpl /tmp/internal/configs/version1/nginx$PLUS.tmpl \
/tmp/internal/configs/version2/nginx$PLUS.virtualserver.tmpl /tmp/internal/configs/version2/nginx$PLUS.transportserver.tmpl / \
From 785a8933f172f83feea21d6bfcc5e38c36f41e8a Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 12:15:31 +0100
Subject: [PATCH 32/38] remove PR tags
---
.github/workflows/build-oss.yml | 1 -
.github/workflows/build-plus.yml | 1 -
2 files changed, 2 deletions(-)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index ec0fec9183..1bcd383247 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -114,7 +114,6 @@ jobs:
suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}
tags: |
type=raw,value=${{ inputs.tag }}
- type=ref,event=pr
labels: |
org.opencontainers.image.description=NGINX Ingress Controller for Kubernetes
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/main/README.md
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 6897851812..a6e1649560 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -132,7 +132,6 @@ jobs:
suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}${{ contains(inputs.target, 'aws') && '-mktpl' || '' }}${{ contains(inputs.image, 'fips') && '-fips' || ''}}
tags: |
type=raw,value=${{ inputs.tag }}
- type=ref,event=pr
labels: |
org.opencontainers.image.description=NGINX Plus Ingress Controller for Kubernetes
env:
From 7273936ce6fcf57f141c017f341755d71582d02d Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 12:23:13 +0100
Subject: [PATCH 33/38] fix image build logic
---
.github/workflows/build-oss.yml | 2 +-
.github/workflows/build-plus.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index 1bcd383247..797651ca97 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -169,7 +169,7 @@ jobs:
BUILD_OS=${{ inputs.image }}
${{ inputs.authenticated && format('PREBUILT_BASE_IMG={0}', steps.base_exists.outputs.image) }}
IC_VERSION=${{ (github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/release-')) && 'CI' || steps.meta.outputs.version }}
- if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
+ if: ${{ steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@595be6a0f6560a0a8fc419ddf630567fc623531d # 0.22.0
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index a6e1649560..4d44ea5898 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -189,7 +189,7 @@ jobs:
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
"nginx-repo.key=${{ inputs.nap-modules != '' && secrets.NGINX_AP_KEY || secrets.NGINX_KEY }}"
${{ contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
+ if: ${{ steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Extract image name for Trivy
id: trivy-tag
From bc9ffa75a9f6d6dc94e6bb1aedb2e2f77722eeb0 Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 13:45:19 +0100
Subject: [PATCH 34/38] remove skopeo sha
---
tests/Dockerfile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/Dockerfile b/tests/Dockerfile
index c8cf24f6ec..6e721e87e8 100644
--- a/tests/Dockerfile
+++ b/tests/Dockerfile
@@ -3,7 +3,7 @@
FROM kindest/node:v1.30.0@sha256:047357ac0cfea04663786a612ba1eaba9702bef25227a794b52890dd8bcd692e
# this is here so we can grab the latest version of skopeo and have dependabot keep it up to date
-FROM quay.io/skopeo/stable:v1.15.1@sha256:981737142fd7ac5315561fc1e39d42203b6efa97ddd2870bde0204b791574efa
+FROM quay.io/skopeo/stable:v1.15.1
FROM python:3.12@sha256:00389e020fe42a6c74a8f091ce9b28324422d084efdff26eabe93bc4ae9a110b
From 19f28d5043644daad4e76ed0a8cd41802787776a Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 14:57:45 +0100
Subject: [PATCH 35/38] change how IC_VERSION is calculated, fix version label
bug
---
.github/workflows/build-oss.yml | 48 +++++++++++++++++---------------
.github/workflows/build-plus.yml | 36 +++++++++++++-----------
build/Dockerfile | 38 +++++++++++++++++++++++--
3 files changed, 82 insertions(+), 40 deletions(-)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index 797651ca97..26fd5fba30 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -29,6 +29,9 @@ on:
required: false
type: boolean
default: false
+ ic-version:
+ required: false
+ type: string
defaults:
run:
@@ -77,6 +80,27 @@ jobs:
password: ${{ steps.auth.outputs.access_token }}
if: ${{ inputs.authenticated }}
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
+ with:
+ context: workflow
+ images: |
+ name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
+ flavor: |
+ suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}
+ tags: |
+ type=raw,value=${{ inputs.tag }}
+ labels: |
+ org.opencontainers.image.description=NGINX Ingress Controller for Kubernetes
+ io.artifacthub.package.readme-url=https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/main/README.md
+ io.artifacthub.package.logo-url=https://docs.nginx.com/nginx-ingress-controller/images/icons/NGINX-Ingress-Controller-product-icon.svg
+ io.artifacthub.package.maintainers=[{"name":"NGINX Inc","email":"kubernetes@nginx.com"}]
+ io.artifacthub.package.license=Apache-2.0
+ io.artifacthub.package.keywords=kubernetes,ingress,nginx,controller
+ env:
+ DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
+
- name: Check if base images exist
id: base_exists
run: |
@@ -101,29 +125,9 @@ jobs:
no-cache: true
build-args: |
BUILD_OS=${{ inputs.image }}
+ IC_VERSION=${{ inputs.ic-version && inputs.ic-version || steps.meta.outputs.version }}
if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 'true' }}
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
- with:
- context: workflow
- images: |
- name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
- flavor: |
- suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}
- tags: |
- type=raw,value=${{ inputs.tag }}
- labels: |
- org.opencontainers.image.description=NGINX Ingress Controller for Kubernetes
- io.artifacthub.package.readme-url=https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/main/README.md
- io.artifacthub.package.logo-url=https://docs.nginx.com/nginx-ingress-controller/images/icons/NGINX-Ingress-Controller-product-icon.svg
- io.artifacthub.package.maintainers=[{"name":"NGINX Inc","email":"kubernetes@nginx.com"}]
- io.artifacthub.package.license=Apache-2.0
- io.artifacthub.package.keywords=kubernetes,ingress,nginx,controller
- env:
- DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
-
- name: Check if target image exists
id: target_exists
run: |
@@ -168,7 +172,7 @@ jobs:
build-args: |
BUILD_OS=${{ inputs.image }}
${{ inputs.authenticated && format('PREBUILT_BASE_IMG={0}', steps.base_exists.outputs.image) }}
- IC_VERSION=${{ (github.event_name == 'pull_request' || startsWith(github.ref, 'refs/heads/release-')) && 'CI' || steps.meta.outputs.version }}
+ IC_VERSION=${{ inputs.ic-version && inputs.ic-version || steps.meta.outputs.version }}
if: ${{ steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Run Trivy vulnerability scanner
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 4d44ea5898..0c1a09984d 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -35,6 +35,9 @@ on:
required: false
type: boolean
default: false
+ ic-version:
+ required: false
+ type: string
defaults:
run:
@@ -91,6 +94,21 @@ jobs:
echo "name=${name}" >> $GITHUB_OUTPUT
if: ${{ inputs.nap-modules != '' }}
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
+ with:
+ images: |
+ name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(inputs.nap-modules, 'dos') && '-dos' || '' }}${{ contains(inputs.nap-modules, 'waf') && '-nap' || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}/nginx-plus-ingress
+ flavor: |
+ suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}${{ contains(inputs.target, 'aws') && '-mktpl' || '' }}${{ contains(inputs.image, 'fips') && '-fips' || ''}}
+ tags: |
+ type=raw,value=${{ inputs.tag }}
+ labels: |
+ org.opencontainers.image.description=NGINX Plus Ingress Controller for Kubernetes
+ env:
+ DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
+
- name: Check if base images exist
id: base_exists
run: |
@@ -115,6 +133,7 @@ jobs:
no-cache: true
build-args: |
BUILD_OS=${{ inputs.image }}
+ IC_VERSION=${{ inputs.ic-version && inputs.ic-version || steps.meta.outputs.version }}
${{ inputs.nap-modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
secrets: |
"nginx-repo.crt=${{ inputs.nap-modules != '' && secrets.NGINX_AP_CRT || secrets.NGINX_CRT }}"
@@ -122,21 +141,6 @@ jobs:
${{ inputs.nap-modules != '' && contains(inputs.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
if: ${{ inputs.authenticated && steps.base_exists.outputs.exists != 'true' }}
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
- with:
- images: |
- name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(inputs.nap-modules, 'dos') && '-dos' || '' }}${{ contains(inputs.nap-modules, 'waf') && '-nap' || '' }}${{ contains(inputs.image, 'v5') && '-v5' || '' }}/nginx-plus-ingress
- flavor: |
- suffix=${{ contains(inputs.image, 'ubi') && '-ubi' || '' }}${{ contains(inputs.image, 'alpine') && '-alpine' || '' }}${{ contains(inputs.target, 'aws') && '-mktpl' || '' }}${{ contains(inputs.image, 'fips') && '-fips' || ''}}
- tags: |
- type=raw,value=${{ inputs.tag }}
- labels: |
- org.opencontainers.image.description=NGINX Plus Ingress Controller for Kubernetes
- env:
- DOCKER_METADATA_ANNOTATIONS_LEVELS: manifest,index
-
- name: Check if target image exists
id: target_exists
run: |
@@ -181,7 +185,7 @@ jobs:
build-args: |
BUILD_OS=${{ inputs.image }}
${{ inputs.authenticated && format('PREBUILT_BASE_IMG={0}', steps.base_exists.outputs.image ) }}
- IC_VERSION=${{ steps.meta.outputs.version }}
+ IC_VERSION=${{ inputs.ic-version && inputs.ic-version || steps.meta.outputs.version }}
${{ inputs.nap-modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.name) || '' }}
${{ (contains(inputs.target, 'aws') && inputs.nap-modules != '') && format('NAP_MODULES_AWS={0}', steps.nap_modules.outputs.modules) || '' }}
${{ contains(inputs.image, 'v5') && 'WAF_VERSION=v5' || '' }}
diff --git a/build/Dockerfile b/build/Dockerfile
index d75b0ac6c0..ea07f3b626 100644
--- a/build/Dockerfile
+++ b/build/Dockerfile
@@ -116,6 +116,8 @@ USER 101
FROM alpine:3.19@sha256:c5b1261d6d3e43071626931fc004f70149baeba2c8ec672bd4f27761f8e1ad6b as alpine-plus
ARG NGINX_PLUS_VERSION
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
+
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/apk/cert.key,mode=0644 \
--mount=type=bind,from=alpine-opentracing-lib,target=/tmp/ot/ \
@@ -131,6 +133,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
############################################# Base image for Alpine with NGINX Plus and FIPS #############################################
FROM alpine-plus as alpine-plus-fips
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \
mkdir -p /usr/ssl \
@@ -143,6 +148,9 @@ RUN --mount=type=bind,from=alpine-fips-3.19,target=/tmp/fips/ \
FROM alpine:3.17@sha256:53cf9478b76f4c8fae126acbdfb79bed6e69e628faff572ebe4a029d3d247d98 as alpine-plus-nap-fips
ARG NGINX_PLUS_VERSION
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
--mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
@@ -176,6 +184,9 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
FROM alpine:3.17@sha256:53cf9478b76f4c8fae126acbdfb79bed6e69e628faff572ebe4a029d3d247d98 as alpine-plus-nap-v5-fips
ARG NGINX_PLUS_VERSION
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
--mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \
@@ -205,6 +216,9 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
############################################# Base image for Debian with NGINX Plus #############################################
FROM debian:12-slim@sha256:67f3931ad8cb1967beec602d8c0506af1e37e8d73c2a0b38b181ec5d8560d395 AS debian-plus
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
@@ -230,6 +244,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
FROM debian:11-slim@sha256:acc5810124f0929ab44fc7913c0ad936b074cbd3eadf094ac120190862ba36c4 as debian-plus-nap
ARG NAP_MODULES
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -293,6 +310,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
FROM debian-plus as debian-plus-nap-v5
ARG NAP_MODULES
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -319,6 +339,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
############################################# Base image for UBI with NGINX Plus #############################################
FROM ubi-minimal AS ubi-plus
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
@@ -339,6 +362,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
FROM ubi-minimal as ubi-9-plus-nap
ARG NAP_MODULES
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -380,6 +406,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
FROM ubi-minimal as ubi-9-plus-nap-v5
ARG NAP_MODULES
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -422,6 +451,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
FROM redhat/ubi8@sha256:143123d85045df426c5bbafc6863659880ebe276eb02c77ee868b88d08dbd05d as ubi-8-plus-nap
ARG NAP_MODULES
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -483,6 +515,9 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
FROM redhat/ubi8@sha256:143123d85045df426c5bbafc6863659880ebe276eb02c77ee868b88d08dbd05d as ubi-8-plus-nap-v5
ARG NAP_MODULES
ARG NGINX_AGENT
+ARG NGINX_PLUS_VERSION
+
+ENV NGINX_VERSION=${NGINX_PLUS_VERSION}
RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode=0644 \
--mount=type=secret,id=nginx-repo.key,dst=/etc/ssl/nginx/nginx-repo.key,mode=0644 \
@@ -531,7 +566,6 @@ ARG BUILD_OS
ARG IC_VERSION
ARG TARGETPLATFORM
ARG NAP_MODULES=none
-ARG NGINX_PLUS_VERSION
RUN --mount=type=bind,target=/tmp \
--mount=type=bind,from=nginx-files,src=common.sh,target=/usr/local/bin/common.sh \
@@ -551,7 +585,7 @@ LABEL org.opencontainers.image.version="${IC_VERSION}" \
org.opencontainers.image.vendor="NGINX Inc " \
org.nginx.kic.image.build.target="${TARGETPLATFORM}" \
org.nginx.kic.image.build.os="${BUILD_OS}" \
- org.nginx.kic.image.build.nginx.version="${NGINX_PLUS_VERSION}${NGINX_VERSION}"
+ org.nginx.kic.image.build.nginx.version="${NGINX_VERSION}"
############################################# Build nginx-ingress in golang container #############################################
From af932a798b26be0e60b962f36f63d773abe2f32c Mon Sep 17 00:00:00 2001
From: Eoin O'Shaughnessy
Date: Tue, 18 Jun 2024 15:34:52 +0100
Subject: [PATCH 36/38] add cache miss failures for oss and plus
---
.github/workflows/build-oss.yml | 1 +
.github/workflows/build-plus.yml | 1 +
2 files changed, 2 insertions(+)
diff --git a/.github/workflows/build-oss.yml b/.github/workflows/build-oss.yml
index 26fd5fba30..24f8103a10 100644
--- a/.github/workflows/build-oss.yml
+++ b/.github/workflows/build-oss.yml
@@ -149,6 +149,7 @@ jobs:
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ inputs.go-md5 }}
+ fail-on-cache-miss: true
if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Build Docker image
diff --git a/.github/workflows/build-plus.yml b/.github/workflows/build-plus.yml
index 0c1a09984d..c70de87006 100644
--- a/.github/workflows/build-plus.yml
+++ b/.github/workflows/build-plus.yml
@@ -162,6 +162,7 @@ jobs:
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ inputs.go-md5 }}
+ fail-on-cache-miss: true
if: ${{ inputs.authenticated || steps.base_exists.outputs.exists != 'true' || steps.target_exists.outputs.exists != 'true' }}
- name: Build Docker image
From 93f32bb7089ff9725df8b6ee38b9baeb5482f69c Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 17:11:31 +0100
Subject: [PATCH 37/38] add wafv5 to edge publish flow
---
.github/workflows/image-promotion.yml | 16 ++++++++++++++++
.github/workflows/release.yml | 1 +
2 files changed, 17 insertions(+)
diff --git a/.github/workflows/image-promotion.yml b/.github/workflows/image-promotion.yml
index 9f961b5ecd..e3983ee0e7 100644
--- a/.github/workflows/image-promotion.yml
+++ b/.github/workflows/image-promotion.yml
@@ -194,6 +194,22 @@ jobs:
target: goreleaser
platforms: "linux/amd64"
nap_modules: waf
+ - image: alpine-plus-nap-v5-fips
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: debian-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-9-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
+ - image: ubi-8-plus-nap-v5
+ target: goreleaser
+ platforms: "linux/amd64"
+ nap_modules: waf
uses: ./.github/workflows/build-plus.yml
with:
platforms: ${{ matrix.platforms }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b69e6b78cb..e3aa48d963 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,4 +1,5 @@
name: Release NIC
+run-name: ${{ inputs.dry_run && '[DRY RUN] ' || '' }}Release NIC ${{ inputs.nic_version }} from ${{ inputs.release_branch }} by @${{ github.actor }}
on:
workflow_dispatch:
From 47fb3339c6f44d1fced703c6de4aa10bbcd8c103 Mon Sep 17 00:00:00 2001
From: Paul Abel
Date: Tue, 18 Jun 2024 17:44:09 +0100
Subject: [PATCH 38/38] correct waf v5 retag
---
.github/scripts/copy-images.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/scripts/copy-images.sh b/.github/scripts/copy-images.sh
index d5eaba3cc5..dbff09ac56 100755
--- a/.github/scripts/copy-images.sh
+++ b/.github/scripts/copy-images.sh
@@ -42,7 +42,7 @@ SOURCE_NAP_WAF_DOS_IMAGE_PREFIX=${SOURCE_NAP_WAF_DOS_IMAGE_PREFIX:-"nginx-ic-dos
TARGET_PLUS_IMAGE_PREFIX=${TARGET_PLUS_IMAGE_PREFIX:-"nginx-ic/nginx-plus-ingress"}
TARGET_NAP_WAF_IMAGE_PREFIX=${TARGET_NAP_WAF_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
-TARGET_NAP_WAFV5_IMAGE_PREFIX=${TARGET_NAP_WAFV5_IMAGE_PREFIX:-"nginx-ic-nap/nginx-plus-ingress"}
+TARGET_NAP_WAFV5_IMAGE_PREFIX=${TARGET_NAP_WAFV5_IMAGE_PREFIX:-"nginx-ic-nap-v5/nginx-plus-ingress"}
TARGET_NAP_DOS_IMAGE_PREFIX=${TARGET_NAP_DOS_IMAGE_PREFIX:-"nginx-ic-dos/nginx-plus-ingress"}
TARGET_NAP_WAF_DOS_IMAGE_PREFIX=${TARGET_NAP_WAF_DOS_IMAGE_PREFIX:-"nginx-ic-dos-nap/nginx-plus-ingress"}