Skip to content

Build WAF image in pipeline #3565

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

Draft
wants to merge 3 commits into
base: feat/nap-waf
Choose a base branch
from
Draft
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
27 changes: 23 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,30 @@ 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: Inspect SBOM and output manifest
run: |
if [[ "${{ inputs.image }}" == "plus-waf" ]]; then
# For plus-waf, use syft directly
echo "Generating SBOM for plus-waf using syft..."

# Install syft if not available
if ! command -v syft >/dev/null 2>&1; then
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin
fi

# Generate SBOM using syft directly for plus-waf (known to work with NAP WAF)
syft localhost:5000/nginx-gateway-fabric/${{ inputs.image }}:${{ steps.meta.outputs.version }} -o spdx-json > sbom-${{ inputs.image }}.json
echo "Generated SBOM using syft for plus-waf"
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 +195,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
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"
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe I am overthinking this but shouldn't the image names be same in pipeline and these defaults?

why is it plus-waf in workflows and different here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, this is still a draft, I haven't finalised the image names with the team managing the registry yet! I just need a PR to make sure the pipeline is working, sorry for the confusion!

defaultImagePullPolicy = corev1.PullIfNotPresent

// WAF container defaults.
defaultWAFEnforcerImagePath = "private-registry.nginx.com/nap/waf-enforcer"
Expand Down Expand Up @@ -988,6 +989,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
Loading