Skip to content
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

add license secret and mgmt config map for r33 #6888

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions .github/actions/smoke-tests/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ inputs:
registry-token:
description: JWT token for accessing container registry
required: false
plus-jwt:
description: JWT for NGINX Plus
required: false

outputs:
test-results-name:
Expand Down Expand Up @@ -101,6 +104,7 @@ runs:
--durations=10 \
--show-ic-logs=yes \
--ad-secret=${{ inputs.azure-ad-secret }} \
--plus-jwt=${{ inputs.plus-jwt }} \
-m ${{ inputs.marker != '' && inputs.marker || '""' }}
working-directory: ./tests
shell: bash
1 change: 1 addition & 0 deletions .github/workflows/regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ jobs:
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
registry-token: ${{ steps.auth.outputs.access_token }}
test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt', './tests/Dockerfile') || 'latest' }}"
plus-jwt: ${{ secrets.PLUS_JWT }}

- name: Upload Test Results
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/setup-smoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ jobs:
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
registry-token: ${{ steps.auth.outputs.access_token }}
test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt', './tests/Dockerfile') || 'latest' }}"
plus-jwt: ${{ secrets.PLUS_JWT }}
if: ${{ steps.stable_exists.outputs.exists != 'true' }}

- name: Upload Test Results
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/single-image-regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,4 @@ jobs:
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
registry-token: ${{ steps.auth.outputs.access_token }}
test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ inputs.test-image-tag }}"
plus-jwt: ${{ secrets.PLUS_JWT }}
12 changes: 6 additions & 6 deletions build/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1.6
ARG BUILD_OS=debian
ARG NGINX_PLUS_VERSION=R32
ARG NGINX_PLUS_VERSION=R33
ARG DOWNLOAD_TAG=edge
ARG DEBIAN_FRONTEND=noninteractive
ARG PREBUILT_BASE_IMG=nginx/nginx-ingress:${DOWNLOAD_TAG}
Expand Down Expand Up @@ -198,7 +198,7 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \
&& 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~=32.5.144 \
&& apk add --no-cache app-protect-module-plus~=33.5.210 \
&& sed -i -e '/nginx.com/d' /etc/apk/repositories \
&& nap-waf.sh \
&& if [ "${NGINX_AGENT}" = "true" ]; then \
Expand Down Expand Up @@ -279,7 +279,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& if [ "${NGINX_AGENT}" = "true" ]; then agent.sh; fi \
&& if [ -z "${NAP_MODULES##*dos*}" ]; then nap-dos.sh; fi

############################################# Base image for Debian with NGINX Plus and App Protect WAFv5/DoS #############################################
############################################# Base image for Debian with NGINX Plus and App Protect WAFv5 #############################################
FROM debian-plus AS debian-plus-nap-v5
ARG NAP_MODULES
ARG NGINX_AGENT
Expand All @@ -300,7 +300,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& 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-plugin=6.3.0* app-protect-module-plus=32+5.144* nginx-plus-module-appprotect=32+5.144*; \
apt-get install --no-install-recommends --no-install-suggests -y app-protect-module-plus=33+5.210*; \
rm -f /etc/apt/sources.list.d/app-protect.sources; \
nap-waf.sh; \
fi \
Expand Down Expand Up @@ -430,7 +430,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& if [ "${NGINX_AGENT}" = "true" ]; then microdnf --nodocs install -y nginx-agent; fi \
&& if [ -z "${NAP_MODULES##*waf*}" ]; then \
cp /tmp/app-protect-9.repo /etc/yum.repos.d/app-protect-9.repo \
&& microdnf --nodocs install -y app-protect-module-plus-32+5.144* \
&& microdnf --nodocs install -y app-protect-module-plus-33+5.210* \
&& nap-waf.sh \
&& rm -f /etc/yum.repos.d/app-protect-9.repo; \
fi \
Expand Down Expand Up @@ -517,7 +517,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/ssl/nginx/nginx-repo.crt,mode
&& 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-32+5.144*; \
dnf --nodocs install -y app-protect-module-plus-33+5.210*; \
fi \
&& subscription-manager unregister \
&& if [ -z "${NAP_MODULES##*waf*}" ]; then \
Expand Down
2 changes: 1 addition & 1 deletion build/dependencies/Dockerfile.ubi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1.8
FROM nginx:1.27.2@sha256:bc5eac5eafc581aeda3008b4b1f07ebba230de2f27d47767129a6a905c84f470 AS nginx
FROM nginx:1.27.3@sha256:0c86dddac19f2ce4fd716ac58c0fd87bf69bfd4edabfd6971fb885bafd12a00b AS nginx

FROM redhat/ubi9:9.4@sha256:ee0b908e958a1822afc57e5d386d1ea128eebe492cb2e01b6903ee19c133ea75 AS rpm-build
ARG NGINX
Expand Down
21 changes: 21 additions & 0 deletions charts/nginx-ingress/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ Expand the name of the configmap used for NGINX Agent.
{{- end -}}
{{- end -}}

{{/*
Expand the name of the mgmt configmap.
*/}}
{{- define "nginx-ingress.mgmtConfigName" -}}
{{- if .Values.controller.mgmt.customConfigMap -}}
{{ .Values.controller.mgmt.customConfigMap }}
{{- else -}}
{{- default (printf "%s-mgmt" (include "nginx-ingress.fullname" .)) -}}
{{- end -}}
{{- end -}}

{{/*
Expand license token secret name.
*/}}
{{- define "nginx-ingress.licenseTokenSecretName" -}}
{{- .Values.controller.mgmt.licenseTokenSecretName -}}
{{- end -}}

{{/*
Expand leader election lock name.
*/}}
Expand Down Expand Up @@ -226,6 +244,9 @@ Build the args for the service binary.
- -app-protect-dos-memory={{ .Values.controller.appprotectdos.memory }}
{{ end }}
- -nginx-configmaps=$(POD_NAMESPACE)/{{ include "nginx-ingress.configName" . }}
{{- if .Values.controller.nginxplus }}
- -mgmt-configmap=$(POD_NAMESPACE)/{{ include "nginx-ingress.mgmtConfigName" . }}
{{- end }}
{{- if .Values.controller.defaultTLS.secret }}
- -default-server-tls-secret={{ .Values.controller.defaultTLS.secret }}
{{ else if and (.Values.controller.defaultTLS.cert) (.Values.controller.defaultTLS.key) }}
Expand Down
19 changes: 19 additions & 0 deletions charts/nginx-ingress/templates/controller-configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,22 @@ data:
nginx-agent.conf: |-
{{ include "nginx-ingress.agentConfiguration" . | indent 4 }}
{{- end }}
---
{{- if and .Values.controller.nginxplus (eq (.Values.controller.mgmt.customConfigMap | default "") "") }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "nginx-ingress.mgmtConfigName" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "nginx-ingress.labels" . | nindent 4 }}
{{- if .Values.controller.config.annotations }}
annotations:
{{ toYaml .Values.controller.config.annotations | indent 4 }}
{{- end }}
data:
license-token-secret-name: {{ include "nginx-ingress.licenseTokenSecretName" . }}
{{- if hasKey .Values.controller.mgmt "enforceInitialReport" }}
enforce-initial-report: {{ quote .Values.controller.mgmt.enforceInitialReport }}
{{- end }}
{{- end }}
31 changes: 31 additions & 0 deletions charts/nginx-ingress/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,37 @@
}
]
},
"mgmt": {
"type": "object",
"default": {},
"title": "The mgmt block Schema",
"properties": {
"licenseTokenSecretName": {
"type": "string",
"default": "",
"title": "The licenseTokenSecretName Schema",
"examples": [
"nginx-plus-secret",
"license-token",
"license"
]
},
"enforceInitialReport": {
"type": "boolean",
"default": false,
"title": "The enforceInitialReport Schema",
"examples": [
true,
false
]
}
},
"examples": [
{
"licenseTokenSecretName": "license-token"
}
]
},
"nginxReloadTimeout": {
"type": "integer",
"default": 0,
Expand Down
8 changes: 8 additions & 0 deletions charts/nginx-ingress/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ controller:
## Deploys the Ingress Controller for NGINX Plus.
nginxplus: false

## Configures NGINX mgmt block for NGINX Plus
mgmt:
## Secret name of license token for NGINX Plus
licenseTokenSecretName: "license-token" # required for NGINX Plus

## Enables the 180-day grace period for sending the initial usage report
# enforceInitialReport: false

## Timeout in milliseconds which the Ingress Controller will wait for a successful NGINX reload after a change or at the initial start.
nginxReloadTimeout: 60000

Expand Down
14 changes: 14 additions & 0 deletions cmd/nginx-ingress/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
but the Ingress Controller is not able to fetch it from Kubernetes API, the Ingress Controller will fail to start.
Format: <namespace>/<name>`)

mgmtConfigMap = flag.String("mgmt-configmap", "",
`A ConfigMap resource for customizing NGINX configuration. If a ConfigMap is set,
but the Ingress Controller is not able to fetch it from Kubernetes API, the Ingress Controller will fail to start.
Format: <namespace>/<name>`)

nginxPlus = flag.Bool("nginx-plus", false, "Enable support for NGINX Plus")

appProtect = flag.Bool("enable-app-protect", false, "Enable support for NGINX App Protect. Requires -nginx-plus.")
Expand Down Expand Up @@ -258,6 +263,11 @@
*enableDynamicWeightChangesReload = false
}

if *mgmtConfigMap != "" && !*nginxPlus {
nl.Warn(l, "mgmt-configmap flag requires -nginx-plus, mgmt configmap will not be used")
*mgmtConfigMap = ""
}

Check warning on line 269 in cmd/nginx-ingress/flags.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/flags.go#L266-L269

Added lines #L266 - L269 were not covered by tests

mustValidateInitialChecks(ctx)
mustValidateWatchedNamespaces(ctx)
mustValidateFlags(ctx)
Expand Down Expand Up @@ -419,6 +429,10 @@
if *agent && !*appProtect {
nl.Fatal(l, "NGINX Agent is used to enable the Security Monitoring dashboard and requires NGINX App Protect to be enabled")
}

if *nginxPlus && *mgmtConfigMap == "" {
nl.Fatal(l, "NGINX Plus requires a mgmt ConfigMap to be set")
}

Check warning on line 435 in cmd/nginx-ingress/flags.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/flags.go#L433-L435

Added lines #L433 - L435 were not covered by tests
}

// validateNamespaceNames validates the namespaces are in the correct format
Expand Down
58 changes: 54 additions & 4 deletions cmd/nginx-ingress/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
appProtectv5BundleFolder = "/etc/app_protect/bundles/"
fatalEventFlushTime = 200 * time.Millisecond
secretErrorReason = "SecretError"
configMapErrorReason = "ConfigMapError"
)

func main() {
Expand Down Expand Up @@ -150,6 +151,14 @@

go updateSelfWithVersionInfo(ctx, eventRecorder, kubeClient, version, appProtectVersion, agentVersion, nginxVersion, 10, time.Second*5)

var mgmtCfgParams *configs.MGMTConfigParams
if *nginxPlus {
mgmtCfgParams = processMGMTConfigMap(kubeClient, configs.NewDefaultMGMTConfigParams(ctx), eventRecorder, pod)
if err := processLicenseSecret(kubeClient, nginxManager, mgmtCfgParams, controllerNamespace); err != nil {
logEventAndExit(ctx, eventRecorder, pod, secretErrorReason, err)
}

Check warning on line 159 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L154-L159

Added lines #L154 - L159 were not covered by tests
}

templateExecutor, templateExecutorV2 := createTemplateExecutors(ctx)

sslRejectHandshake, err := processDefaultServerSecret(kubeClient, nginxManager)
Expand Down Expand Up @@ -199,7 +208,7 @@
AppProtectBundlePath: appProtectBundlePath,
}

mustProcessNginxConfig(staticCfgParams, cfgParams, templateExecutor, nginxManager)
mustProcessNginxConfig(staticCfgParams, cfgParams, mgmtCfgParams, templateExecutor, nginxManager)

Check warning on line 211 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L211

Added line #L211 was not covered by tests

if *enableTLSPassthrough {
var emptyFile []byte
Expand All @@ -215,6 +224,7 @@
NginxManager: nginxManager,
StaticCfgParams: staticCfgParams,
Config: cfgParams,
MGMTCfgParams: mgmtCfgParams,

Check warning on line 227 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L227

Added line #L227 was not covered by tests
TemplateExecutor: templateExecutor,
TemplateExecutorV2: templateExecutorV2,
LatencyCollector: latencyCollector,
Expand Down Expand Up @@ -266,6 +276,7 @@
LeaderElectionLockName: *leaderElectionLockName,
WildcardTLSSecret: *wildcardTLSSecret,
ConfigMaps: *nginxConfigMaps,
MGMTConfigMap: *mgmtConfigMap,

Check warning on line 279 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L279

Added line #L279 was not covered by tests
GlobalConfiguration: *globalConfiguration,
AreCustomResourcesEnabled: *enableCustomResources,
EnableOIDC: *enableOIDC,
Expand Down Expand Up @@ -616,6 +627,22 @@
return isWildcardEnabled, nil
}

func processLicenseSecret(kubeClient *kubernetes.Clientset, nginxManager nginx.Manager, mgmtCfgParams *configs.MGMTConfigParams, controllerNamespace string) error {
licenseSecretNsName := controllerNamespace + "/" + mgmtCfgParams.Secrets.License

secret, err := getAndValidateSecret(kubeClient, licenseSecretNsName, secrets.SecretTypeLicense)
if err != nil {
return fmt.Errorf("license secret: %w", err)
}

Check warning on line 636 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L630-L636

Added lines #L630 - L636 were not covered by tests

bytes, err := configs.GenerateLicenseSecret(secret)
if err != nil {
return err
}
nginxManager.CreateSecret(configs.LicenseSecretFileName, bytes, nginx.ReadWriteOnlyFileMode)
return nil

Check warning on line 643 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L638-L643

Added lines #L638 - L643 were not covered by tests
}

func createGlobalConfigurationValidator() *cr_validation.GlobalConfigurationValidator {
forbiddenListenerPorts := map[int]bool{
80: true,
Expand All @@ -642,9 +669,9 @@

// mustProcessNginxConfig calls internally os.Exit
// if can't generate a valid NGINX config.
func mustProcessNginxConfig(staticCfgParams *configs.StaticConfigParams, cfgParams *configs.ConfigParams, templateExecutor *version1.TemplateExecutor, nginxManager nginx.Manager) {
func mustProcessNginxConfig(staticCfgParams *configs.StaticConfigParams, cfgParams *configs.ConfigParams, mgmtCfgParams *configs.MGMTConfigParams, templateExecutor *version1.TemplateExecutor, nginxManager nginx.Manager) {

Check warning on line 672 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L672

Added line #L672 was not covered by tests
l := nl.LoggerFromContext(cfgParams.Context)
ngxConfig := configs.GenerateNginxMainConfig(staticCfgParams, cfgParams)
ngxConfig := configs.GenerateNginxMainConfig(staticCfgParams, cfgParams, mgmtCfgParams)

Check warning on line 674 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L674

Added line #L674 was not covered by tests
content, err := templateExecutor.ExecuteMainConfigTemplate(ngxConfig)
if err != nil {
nl.Fatalf(l, "Error generating NGINX main config: %v", err)
Expand Down Expand Up @@ -683,14 +710,19 @@
}
secret, err = kubeClient.CoreV1().Secrets(ns).Get(context.TODO(), name, meta_v1.GetOptions{})
if err != nil {
return nil, fmt.Errorf("could not get %v: %w", secretNsName, err)
return nil, fmt.Errorf("could not find %v: %w", secretNsName, err)

Check warning on line 713 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L713

Added line #L713 was not covered by tests
}
switch secretType {
case api_v1.SecretTypeTLS:
err = secrets.ValidateTLSSecret(secret)
if err != nil {
return nil, fmt.Errorf("%v is invalid: %w", secretNsName, err)
}
case secrets.SecretTypeLicense:
err = secrets.ValidateLicenseSecret(secret)
if err != nil {
return secret, err
AlexFenlon marked this conversation as resolved.
Show resolved Hide resolved
}

Check warning on line 725 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L721-L725

Added lines #L721 - L725 were not covered by tests
}
return secret, nil
}
Expand Down Expand Up @@ -909,6 +941,24 @@
return cfgParams
}

func processMGMTConfigMap(kubeClient *kubernetes.Clientset, mgmtCfgParams *configs.MGMTConfigParams, eventLog record.EventRecorder, pod *api_v1.Pod) *configs.MGMTConfigParams {
ctx := mgmtCfgParams.Context
var fatalErr error

ns, name, err := k8s.ParseNamespaceName(*mgmtConfigMap)
if err != nil {
logEventAndExit(ctx, eventLog, pod, configMapErrorReason, fmt.Errorf("error parsing the mgmt-configmap argument: %w", err))
}
cfm, err := kubeClient.CoreV1().ConfigMaps(ns).Get(context.TODO(), name, meta_v1.GetOptions{})
if err != nil {
logEventAndExit(ctx, eventLog, cfm, configMapErrorReason, fmt.Errorf("error when getting mgmt-configmap [%v]: %w", *mgmtConfigMap, err))
}
if mgmtCfgParams, _, fatalErr = configs.ParseMGMTConfigMap(ctx, cfm, eventLog); fatalErr != nil {
jjngx marked this conversation as resolved.
Show resolved Hide resolved
logEventAndExit(ctx, eventLog, cfm, secretErrorReason, fatalErr)
}
return mgmtCfgParams

Check warning on line 959 in cmd/nginx-ingress/main.go

View check run for this annotation

Codecov / codecov/patch

cmd/nginx-ingress/main.go#L944-L959

Added lines #L944 - L959 were not covered by tests
}

func updateSelfWithVersionInfo(ctx context.Context, eventLog record.EventRecorder, kubeClient *kubernetes.Clientset, version, appProtectVersion, agentVersion string, nginxVersion nginx.Version, maxRetries int, waitTime time.Duration) {
l := nl.LoggerFromContext(ctx)
podUpdated := false
Expand Down
7 changes: 7 additions & 0 deletions deployments/common/plus-mgmt-configmap.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config-mgmt
namespace: nginx-ingress
data:
license-token-secret-name: "license-token"
1 change: 1 addition & 0 deletions deployments/deployment/nginx-plus-ingress.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ spec:
args:
- -nginx-plus
- -nginx-configmaps=$(POD_NAMESPACE)/nginx-config
- -mgmt-configmap=$(POD_NAMESPACE)/nginx-config-mgmt
- -report-ingress-status
- -external-service=nginx-ingress
#- -default-server-tls-secret=$(POD_NAMESPACE)/default-server-secret
Expand Down
Loading
Loading