Skip to content

Build WAF image in pipeline #3606

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: feat/nap-waf
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ jobs:
token_format: access_token
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
if: ${{ github.event_name != 'pull_request' && contains(inputs.image, 'plus') }}
if: ${{ github.event_name != 'pull_request' && (contains(inputs.image, 'plus') || inputs.image == 'plus-waf') }}

- name: Login to GAR
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: us-docker.pkg.dev
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ github.event_name != 'pull_request' && contains(inputs.image, 'plus') }}
if: ${{ github.event_name != 'pull_request' && (contains(inputs.image, 'plus') || inputs.image == 'plus-waf') }}

- name: Docker meta
id: meta
Expand All @@ -106,7 +106,9 @@ jobs:
name=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric,enable=${{ inputs.image == 'ngf' && github.event_name != 'pull_request' }}
name=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric/nginx,enable=${{ inputs.image == 'nginx' && github.event_name != 'pull_request' }}
name=docker-mgmt.nginx.com/nginx-gateway-fabric/nginx-plus,enable=${{ inputs.image == 'plus' && github.event_name != 'pull_request' }}
name=docker-mgmt.nginx.com/nginx-gateway-fabric/nginx-plus-nap-waf,enable=${{ inputs.image == 'plus-waf' && github.event_name != 'pull_request' }}
name=us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/nginx-gateway-fabric/nginx-plus,enable=${{ inputs.image == 'plus' && github.event_name != 'pull_request' }}
name=us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/nginx-gateway-fabric/nginx-plus-nap-waf,enable=${{ inputs.image == 'plus-waf' && github.event_name != 'pull_request' }}
name=localhost:5000/nginx-gateway-fabric/${{ inputs.image }}
flavor: |
latest=${{ (inputs.tag != '' && 'true') || 'auto' }}
Expand Down Expand Up @@ -134,7 +136,7 @@ jobs:
- name: Build Docker Image
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with:
file: build/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || '' }}
file: build/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ (inputs.image == 'plus' || inputs.image == 'plus-waf') && '.nginxplus' || '' }}
context: "."
target: ${{ inputs.image == 'ngf' && 'goreleaser' || '' }}
tags: ${{ steps.meta.outputs.tags }}
Expand All @@ -152,13 +154,25 @@ jobs:
NJS_DIR=internal/controller/nginx/modules/src
NGINX_CONF_DIR=internal/controller/nginx/conf
BUILD_AGENT=gha
${{ inputs.image == 'plus-waf' && 'ALPINE_VERSION=3.19' || '' }}
${{ inputs.image == 'plus-waf' && 'INCLUDE_NAP_WAF=true' || '' }}
secrets: |
${{ contains(inputs.image, 'plus') && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
${{ contains(inputs.image, 'plus') && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}

- name: Download Syft
uses: anchore/sbom-action/download-syft@cee1b8e05ae5b2593a75e197229729eabaa9f8ec # v0.20.2
if: ${{ inputs.image == 'plus-waf' }}

- name: Inspect SBOM and output manifest
run: |
if [[ "${{ inputs.image }}" == "plus-waf" ]]; then
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Why does the docker buildx method not work for this?
  2. Should we make this more structured, and have a Download Syft step (like in ci.yml) for this image, rather than too much scripting?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I think including a non open source package causes issues with the inspection. An error like ERROR: template: :1:9: executing "" at <index .SBOM "linux/amd64">: error calling index: can't index item of type imagetools.sbomStub occurs - see https://github.com/nginx/nginx-gateway-fabric/actions/runs/15971343514/job/45043600174
  2. Yeah that makes sense!

# For plus-waf, use syft directly
syft localhost:5000/nginx-gateway-fabric/${{ inputs.image }}:${{ steps.meta.outputs.version }} -o spdx-json > sbom-${{ inputs.image }}.json
else
# For other images, use the standard Docker buildx approach
docker buildx imagetools inspect localhost:5000/nginx-gateway-fabric/${{ inputs.image }}:${{ steps.meta.outputs.version }} --format '{{ json (index .SBOM "linux/amd64").SPDX }}' > sbom-${{ inputs.image }}.json
fi
docker buildx imagetools inspect localhost:5000/nginx-gateway-fabric/${{ inputs.image }}:${{ steps.meta.outputs.version }} --raw

- name: Scan SBOM
Expand All @@ -176,4 +190,4 @@ jobs:
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
category: build-${{ inputs.image }}
if: always()
if: always() && steps.scan.conclusion == 'success'
14 changes: 14 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,20 @@ jobs:
id-token: write # for docker/login to login to NGINX registry
secrets: inherit

build-plus-waf:
name: Build Plus WAF images
needs: [vars, binary]
uses: ./.github/workflows/build.yml
with:
image: plus-waf
platforms: "linux/amd64"
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
packages: write # for docker/build-push-action to push to GHCR
id-token: write # for docker/login to login to NGINX registry
secrets: inherit

functional-tests:
name: Functional tests
needs: [vars, build-oss, build-plus]
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,22 @@ the [Issue Lifecycle](ISSUE_LIFECYCLE.md) document for information on issue crea

The following table lists the software versions NGINX Gateway Fabric supports.

| NGINX Gateway Fabric | Gateway API | Kubernetes | NGINX OSS | NGINX Plus | NGINX Agent |
|----------------------|-------------|------------|-----------|------------|-------------|
| Edge | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.3 |
| 2.0.2 | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.1 |
| 2.0.1 | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.1 |
| 2.0.0 | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.0 |
| 1.6.2 | 1.2.1 | 1.25+ | 1.27.4 | R33 | --- |
| 1.6.1 | 1.2.1 | 1.25+ | 1.27.4 | R33 | --- |
| 1.6.0 | 1.2.1 | 1.25+ | 1.27.3 | R33 | --- |
| 1.5.1 | 1.2.0 | 1.25+ | 1.27.2 | R33 | --- |
| 1.5.0 | 1.2.0 | 1.25+ | 1.27.2 | R33 | --- |
| 1.4.0 | 1.1.0 | 1.25+ | 1.27.1 | R32 | --- |
| 1.3.0 | 1.1.0 | 1.25+ | 1.27.0 | R32 | --- |
| 1.2.0 | 1.0.0 | 1.23+ | 1.25.4 | R31 | --- |
| 1.1.0 | 1.0.0 | 1.23+ | 1.25.3 | n/a | --- |
| 1.0.0 | 0.8.1 | 1.23+ | 1.25.2 | n/a | --- |
| NGINX Gateway Fabric | Gateway API | Kubernetes | NGINX OSS | NGINX Plus | NGINX Agent | NGINX NAP WAF |
|----------------------|-------------|------------|-----------|------------|-------------|---------------|
| Edge | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.3 | 5.7.0 |
| 2.0.2 | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.1 | --- |
| 2.0.1 | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.1 | --- |
| 2.0.0 | 1.3.0 | 1.25+ | 1.28.0 | R34 | v3.0.0 | --- |
| 1.6.2 | 1.2.1 | 1.25+ | 1.27.4 | R33 | --- | --- |
| 1.6.1 | 1.2.1 | 1.25+ | 1.27.4 | R33 | --- | --- |
| 1.6.0 | 1.2.1 | 1.25+ | 1.27.3 | R33 | --- | --- |
| 1.5.1 | 1.2.0 | 1.25+ | 1.27.2 | R33 | --- | --- |
| 1.5.0 | 1.2.0 | 1.25+ | 1.27.2 | R33 | --- | --- |
| 1.4.0 | 1.1.0 | 1.25+ | 1.27.1 | R32 | --- | --- |
| 1.3.0 | 1.1.0 | 1.25+ | 1.27.0 | R32 | --- | --- |
| 1.2.0 | 1.0.0 | 1.23+ | 1.25.4 | R31 | --- | --- |
| 1.1.0 | 1.0.0 | 1.23+ | 1.25.3 | n/a | --- | --- |
| 1.0.0 | 0.8.1 | 1.23+ | 1.25.2 | n/a | --- | --- |

## SBOM (Software Bill of Materials)

Expand Down
11 changes: 8 additions & 3 deletions internal/controller/provisioner/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ const (
defaultServiceType = corev1.ServiceTypeLoadBalancer
defaultServicePolicy = corev1.ServiceExternalTrafficPolicyLocal

defaultNginxImagePath = "ghcr.io/nginx/nginx-gateway-fabric/nginx"
defaultNginxPlusImagePath = "private-registry.nginx.com/nginx-gateway-fabric/nginx-plus"
defaultImagePullPolicy = corev1.PullIfNotPresent
defaultNginxImagePath = "ghcr.io/nginx/nginx-gateway-fabric/nginx"
defaultNginxPlusImagePath = "private-registry.nginx.com/nginx-gateway-fabric/nginx-plus"
defaultNginxPlusWafImagePath = "private-registry.nginx.com/nginx-gateway-fabric/nginx-plus-nap-waf"
defaultImagePullPolicy = corev1.PullIfNotPresent

// WAF container defaults.
defaultWAFEnforcerImagePath = "private-registry.nginx.com/nap/waf-enforcer"
Expand Down Expand Up @@ -1005,6 +1006,10 @@ func (p *NginxProvisioner) buildImage(nProxyCfg *graph.EffectiveNginxProxy) (str
image = defaultNginxPlusImagePath
}

if graph.WAFEnabledForNginxProxy(nProxyCfg) {
image = defaultNginxPlusWafImagePath
}

getImageAndPullPolicy := func(container ngfAPIv1alpha2.ContainerSpec) (string, string, corev1.PullPolicy) {
if container.Image != nil {
if container.Image.Repository != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/provisioner/objects_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ func TestBuildNginxResourceObjects_WAF(t *testing.T) {
// Validate NGINX container (first container)
nginxContainer := template.Spec.Containers[0]
g.Expect(nginxContainer.Name).To(Equal("nginx"))
g.Expect(nginxContainer.Image).To(Equal(fmt.Sprintf("%s:1.0.0", defaultNginxImagePath)))
g.Expect(nginxContainer.Image).To(Equal(fmt.Sprintf("%s:1.0.0", defaultNginxPlusWafImagePath)))

// Check NGINX container has WAF volume mounts
wafVolumeMountNames := []string{
Expand Down
Loading