8000 Add handling of multiple log destinations by rafwegv · Pull Request #2328 · nginx/kubernetes-ingress · GitHub
[go: up one dir, main page]

Skip to content
Merged
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
12 changes: 12 additions & 0 deletions deployments/common/crds/k8s.nginx.org_policies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ spec:
type: boolean
logDest:
type: string
securityLogs:
type: array
items:
description: SecurityLog defines the security log of a WAF policy.
type: object
properties:
apLogConf:
type: string
enable:
type: boolean
logDest:
type: string
status:
description: PolicyStatus is the status of the policy resource
type: object
Expand Down
12 changes: 12 additions & 0 deletions deployments/helm-chart/crds/k8s.nginx.org_policies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ spec:
type: boolean
logDest:
type: string
securityLogs:
type: array
items:
description: SecurityLog defines the security log of a WAF policy.
type: object
properties:
apLogConf:
type: string
enable:
type: boolean
logDest:
type: string
status:
description: PolicyStatus is the status of the policy resource
type: object
Expand Down
11 changes: 7 additions & 4 deletions docs/content/configuration/policy-resource.md
```
Original file line number Diff line number Diff line change
Expand Up @@ -355,17 +355,20 @@ For `kubectl get` and similar commands, you can also use the short name `pol` in

The WAF policy configures NGINX Plus to secure client requests using App Protect policies.

For example, the following policy will enable the referenced APPolicy and APLogConf with the configured log destination:
For example, the following policy will enable the referenced APPolicy. You can configure multiple APLogConfs with log destinations:
```yaml
waf:
enable: true
apPolicy: "default/dataguard-alarm"
securityLog:
enable: true
securityLogs:
- enable: true
apLogConf: "default/logconf"
logDest: "syslog:server=syslog-svc.default:514"
- enable: true
apLogConf: "default/logconf"
logDest: "syslog:server=syslog-svc-secondary.default:514"

> Note: The field `waf.securityLog` is deprecated and will be removed in future releases.It will be ignored if `waf.securityLogs` is populated.
> Note: The feature is implemented using the NGINX Plus [NGINX App Protect Module](https://docs.nginx.com/nginx-app-protect/configuration/).

{{% table %}}
Expand Down
4 changes: 2 additions & 2 deletions examples/custom-resources/waf/waf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ spec:
waf:
enable: true
apPolicy: "default/dataguard-alarm"
securityLog:
enable: true
securityLogs:
- enable: true
apLogConf: "default/logconf"
logDest: "syslog:server=syslog-svc.default:514"
16 changes: 10 additions & 6 deletions internal/configs/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ type MergeableIngresses struct {
}

func generateNginxCfg(ingEx *IngressEx, apResources *AppProtectResources, dosResource *appProtectDosResource, isMinion bool,
baseCfgParams *ConfigParams, isPlus bool, isResolverConfigured bool, staticParams *StaticConfigParams, isWildcardEnabled bool) (version1.IngressNginxConfig, Warnings) {
baseCfgParams *ConfigParams, isPlus bool, isResolverConfigured bool, staticParams *StaticConfigParams, isWildcardEnabled bool,
) (version1.IngressNginxConfig, Warnings) {
hasAppProtect := staticParams.MainAppProtectLoadModule
hasAppProtectDos := staticParams.MainAppProtectDosLoadModule

Expand Down Expand Up @@ -290,7 +291,8 @@ func generateNginxCfg(ingEx *IngressEx, apResources *AppProtectResources, dosRes
}

func generateJWTConfig(owner runtime.Object, secretRefs map[string]*secrets.SecretReference, cfgParams *ConfigParams,
redirectLocationName string) (*version1.JWTAuth, *version1.JWTRedirectLocation, Warnings) {
redirectLocationName string,
) (*version1.JWTAuth, *version1.JWTRedirectLocation, Warnings) {
warnings := newWarnings()

secretRef := secretRefs[cfgParams.JWTKey]
Expand Down Expand Up @@ -326,7 +328,8 @@ func generateJWTConfig(owner runtime.Object, secretRefs map[string]*secrets.Secr
}

func addSSLConfig(server *version1.Server, owner runtime.Object, host string, ingressTLS []networking.IngressTLS,
secretRefs map[string]*secrets.SecretReference, isWildcardEnabled bool) Warnings {
secretRefs map[string]*secrets.SecretReference, isWildcardEnabled bool,
) Warnings {
warnings := newWarnings()

var tlsEnabled bool
Expand Down Expand Up @@ -427,7 +430,8 @@ func upstreamRequiresQueue(name string, ingEx *IngressEx, cfg *ConfigParams) (n
}

func createUpstream(ingEx *IngressEx, name string, backend *networking.IngressBackend, stickyCookie string, cfg *ConfigParams,
isPlus bool, isResolverConfigured bool, isLatencyMetricsEnabled bool) version1.Upstream {
isPlus bool, isResolverConfigured bool, isLatencyMetricsEnabled bool,
) version1.Upstream {
var ups version1.Upstream
labels := version1.UpstreamLabels{
Service: backend.Service.Name,
Expand Down Expand Up @@ -534,8 +538,8 @@ func upstreamMapToSlice(upstreams map[string]version1.Upstream) []version1.Upstr

func generateNginxCfgForMergeableIngresses(mergeableIngs *MergeableIngresses, apResources *AppProtectResources,
dosResource *appProtectDosResource, baseCfgParams *ConfigParams, isPlus bool, isResolverConfigured bool,
staticParams *StaticConfigParams, isWildcardEnabled bool) (version1.IngressNginxConfig, Warnings) {

staticParams *StaticConfigParams, isWildcardEnabled bool,
) (version1.IngressNginxConfig, Warnings) {
var masterServer version1.Server
var locations []version1.Location
var upstreams []version1.Upstream
Expand Down
1 change: 0 additions & 1 deletion internal/configs/version1/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ var (
)

var ingCfg = IngressNginxConfig{

Servers: []Server{
{
Name: "test.example.com",
Expand Down
2 changes: 1 addition & 1 deletion internal/configs/version2/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ type WAF struct {
Enable string
ApPolicy string
ApSecurityLogEnable bool
ApLogConf string
ApLogConf []string
}

// Dos defines Dos configuration.
Expand Down
8 changes: 6 additions & 2 deletions internal/configs/version2/nginx-plus.virtualserver.tmpl
67E5
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,9 @@ server {

{{ if .ApSecurityLogEnable }}
app_protect_security_log_enable on;
app_protect_security_log {{ .ApLogConf }};
{{ range $logconf := .ApLogConf }}
app_protect_security_log {{ $logconf }};
{{ end }}
{{ end }}
{{ end }}

Expand Down Expand Up @@ -370,7 +372,9 @@ server {

{{ if .ApSecurityLogEnable }}
app_protect_security_log_enable on;
app_protect_security_log {{ .ApLogConf }};
{{ range $logconf := .ApLogConf }}
app_protect_security_log {{ $logconf }};
{{ end }}
{{ end }}
{{ end }}

Expand Down
2 changes: 1 addition & 1 deletion internal/configs/version2/templates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ var virtualServerCfg = VirtualServerConfig{
WAF: &WAF{
ApPolicy: "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: "/etc/nginx/waf/nac-logconfs/default-logconf",
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf"},
},
Snippets: []string{"# server snippet"}, A3DB
InternalRedirectLocations: []InternalRedirectLocation{
Expand Down
38 changes: 31 additions & 7 deletions internal/configs/virtualserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -1041,7 +1041,8 @@ func (p *policiesCfg) addWAFConfig(
}
}

if waf.SecurityLog != nil {
if waf.SecurityLog != nil && waf.SecurityLogs == nil {
glog.V(2).Info("the field securityLog is deprecated nad will be removed in future releases. Use field securityLogs instead")
p.WAF.ApSecurityLogEnable = true

logConfKey := waf.SecurityLog.ApLogConf
Expand All @@ -1052,13 +1053,31 @@ func (p *policiesCfg) addWAFConfig(

if logConfPath, ok := apResources.LogConfs[logConfKey]; ok {
logDest := generateString(waf.SecurityLog.LogDest, "syslog:server=localhost:514")
p.WAF.ApLogConf = fmt.Sprintf("%s %s", logConfPath, logDest)
p.WAF.ApLogConf = []string{fmt.Sprintf("%s %s", logConfPath, logDest)}
} else {
res.addWarningf("WAF policy %s references an invalid or non-existing log config %s", polKey, logConfKey)
res.isError = true
}
}

if waf.SecurityLogs != nil {
p.WAF.ApSecurityLogEnable = true
p.WAF.ApLogConf = []string{}
for _, loco := range waf.SecurityLogs {
logConfKey := loco.ApLogConf
hasNamepace := strings.Contains(logConfKey, "/")
if !hasNamepace {
logConfKey = fmt.Sprintf("%v/%v", polNamespace, logConfKey)
}
if logConfPath, ok := apResources.LogConfs[logConfKey]; ok {
logDest := generateString(loco.LogDest, "syslog:server=localhost:514")
p.WAF.ApLogConf = append(p.WAF.ApLogConf, fmt.Sprintf("%s %s", logConfPath, logDest))
} else {
res.addWarningf("WAF policy %s references an invalid or non-existing log config %s", polKey, logConfKey)
res.isError = true
}
}
}
return res
}

Expand Down Expand Up @@ -1575,7 +1594,8 @@ type errorPageDetails struct {
func generateLocation(path string, upstreamName string, upstream conf_v1.Upstream, action *conf_v1.Action,
cfgParams *ConfigParams, errorPages errorPageDetails, internal bool, proxySSLName string,
originalPath string, locSnippets string, enableSnippets bool, retLocIndex int, isVSR bool, vsrName string,
vsrNamespace string, vscWarnings Warnings) (version2.Location, *version2.ReturnLocation) {
vsrNamespace string, vscWarnings Warnings,
) (version2.Location, *version2.ReturnLocation) {
locationSnippets := generateSnippets(enableSnippets, locSnippets, cfgParams.LocationSnippets)

if action.Redirect != nil {
Expand Down Expand Up @@ -1674,7 +1694,8 @@ func generateProxyAddHeaders(proxy *conf_v1.ActionProxy) []version2.AddHeader {

func generateLocationForProxying(path string, upstreamName string, upstream conf_v1.Upstream,
cfgParams *ConfigParams, errorPages []conf_v1.ErrorPage, internal bool, errPageIndex int,
proxySSLName string, proxy *conf_v1.ActionProxy, originalPath string, locationSnippets []string, isVSR bool, vsrName string, vsrNamespace string) version2.Location {
proxySSLName string, proxy *conf_v1.ActionProxy, originalPath string, locationSnippets []string, isVSR bool, vsrName string, vsrNamespace string,
) version2.Location {
return version2.Location{
Path: generatePath(path),
Internal: internal,
Expand Down Expand Up @@ -1741,7 +1762,8 @@ func generateLocationForRedirect(
}

func generateLocationForReturn(path string, locationSnippets []string, actionReturn *conf_v1.ActionReturn,
retLocIndex int) (version2.Location, *version2.ReturnLocation) {
retLocIndex int,
) (version2.Location, *version2.ReturnLocation) {
defaultType := actionReturn.Type
if defaultType == "" {
defaultType = "text/plain"
Expand Down Expand Up @@ -1873,7 +1895,8 @@ func generateDefaultSplitsConfig(

func generateMatchesConfig(route conf_v1.Route, upstreamNamer *upstreamNamer, crUpstreams map[string]conf_v1.Upstream,
variableNamer *variableNamer, index int, scIndex int, cfgParams *ConfigParams, errorPages errorPageDetails,
locSnippets string, enableSnippets bool, retLocIndex int, isVSR bool, vsrName string, vsrNamespace string, vscWarnings Warnings) routingCfg {
locSnippets string, enableSnippets bool, retLocIndex int, isVSR bool, vsrName string, vsrNamespace string, vscWarnings Warnings,
) routingCfg {
// Generate maps
var maps []version2.Map

Expand Down Expand Up @@ -2101,7 +2124,8 @@ func getNameForSourceForMatchesRouteMapFromCondition(condition conf_v1.Condition
}

func (vsc *virtualServerConfigurator) generateSSLConfig(owner runtime.Object, tls *conf_v1.TLS, namespace string,
secretRefs map[string]*secrets.SecretReference, cfgParams *ConfigParams) *version2.SSL {
secretRefs map[string]*secrets.SecretReference, cfgParams *ConfigParams,
) *version2.SSL {
if tls == nil {
return nil
}
Expand Down
48 changes: 35 additions & 13 deletions internal/configs/virtualserver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2938,7 +2938,7 @@ func TestGeneratePolicies(t *testing.T) {
Enable: "on",
ApPolicy: "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: "/etc/nginx/waf/nac-logconfs/default-logconf syslog:server=127.0.0.1:514",
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf syslog:server=127.0.0.1:514"},
},
},
msg: "WAF reference",
Expand Down Expand Up @@ -6723,7 +6723,6 @@ func TestGenerateHealthCheck(t *testing.T) {
msg string
}{
{

upstream: conf_v1.Upstream{
HealthCheck: &conf_v1.HealthCheck{
Enable: true,
Expand Down Expand Up @@ -6905,7 +6904,6 @@ func TestGenerateGrpcHealthCheck(t *testing.T) {
msg string
}{
{

upstream: conf_v1.Upstream{
HealthCheck: &conf_v1.HealthCheck{
Enable: true,
Expand Down Expand Up @@ -8248,7 +8246,6 @@ func TestAddWafConfig(t *testing.T) {
msg string
}{
{

wafInput: &conf_v1.WAF{
Enable: true,
},
Expand All @@ -8265,7 +8262,6 @@ func TestAddWafConfig(t *testing.T) {
msg: "valid waf config, default App Protect config",
},
{

wafInput: &conf_v1.WAF{
Enable: true,
ApPolicy: "dataguard-alarm",
Expand All @@ -8288,13 +8284,42 @@ func TestAddWafConfig(t *testing.T) {
wafConfig: &version2.WAF{
ApPolicy: "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: "/etc/nginx/waf/nac-logconfs/default-logconf",
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf"},
},
expected: &validationResults{isError: false},
msg: "valid waf config",
},
{
wafInput: &conf_v1.WAF{
Enable: true,
ApPolicy: "dataguard-alarm",
SecurityLogs: []*conf_v1.SecurityLog{
{
Enable: true,
ApLogConf: "logconf",
LogDest: "syslog:server=127.0.0.1:514",
},
},
},
polKey: "default/waf-policy",
polNamespace: "default",
apResources: &appProtectResourcesForVS{
Policies: map[string]string{
"default/dataguard-alarm": "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
},
LogConfs: map[string]string{
"default/logconf": "/etc/nginx/waf/nac-logconfs/default-logconf",
},
},
wafConfig: &version2.WAF{
ApPolicy: "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf"},
},
expected: &validationResults{isError: false},
msg: "valid waf config",
},
{

wafInput: &conf_v1.WAF{
Enable: true,
ApPolicy: "default/dataguard-alarm",
Expand All @@ -8315,7 +8340,7 @@ func TestAddWafConfig(t *testing.T) {
wafConfig: &version2.WAF{
ApPolicy: "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: "/etc/nginx/waf/nac-logconfs/default-logconf",
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf"},
},
expected: &validationResults{
isError: true,
Expand All @@ -8326,7 +8351,6 @@ func TestAddWafConfig(t *testing.T) {
msg: "invalid waf config, apLogConf references non-existing log conf",
},
{

wafInput: &conf_v1.WAF{
Enable: true,
ApPolicy: "default/dataguard-alarm",
Expand All @@ -8346,7 +8370,7 @@ func TestAddWafConfig(t *testing.T) {
wafConfig: &version2.WAF{
ApPolicy: "/etc/nginx/waf/nac-policies/default-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: "/etc/nginx/waf/nac-logconfs/default-logconf",
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/default-logconf"},
},
expected: &validationResults{
isError: true,
Expand All @@ -8357,7 +8381,6 @@ func TestAddWafConfig(t *testing.T) {
msg: "invalid waf config, apLogConf references non-existing ap conf",
},
{

wafInput: &conf_v1.WAF{
Enable: true,
ApPolicy: "ns1/dataguard-alarm",
Expand All @@ -8380,13 +8403,12 @@ func TestAddWafConfig(t *testing.T) {
wafConfig: &version2.WAF{
ApPolicy: "/etc/nginx/waf/nac-policies/ns1-dataguard-alarm",
ApSecurityLogEnable: true,
ApLogConf: "/etc/nginx/waf/nac-logconfs/ns2-logconf",
ApLogConf: []string{"/etc/nginx/waf/nac-logconfs/ns2-logconf"},
},
expected: &validationResults{},
msg: "valid waf config, cross ns reference",
},
{

wafInput: &conf_v1.WAF{
Enable: false,
ApPolicy: "dataguard-alarm",
Expand Down
Loading
0