8000 AP: add support for multiple log configs · nginx/kubernetes-ingress@0bf0a0a · GitHub
[go: up one dir, main page]

Skip to content

Commit 0bf0a0a

Browse files
author
Rafal Wegrzycki
committed
AP: add support for multiple log configs
1 parent 73b7d02 commit 0bf0a0a

File tree

9 files changed

+104
-70
lines changed

9 files changed

+104
-70
lines changed

internal/configs/configurator.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,20 +1221,21 @@ func createSpiffeCert(certs []*x509.Certificate) []byte {
12211221
return pemData
12221222
}
12231223

1224-
func (cnf *Configurator) updateApResources(ingEx *IngressEx) map[string]string {
1225-
apRes := make(map[string]string)
1224+
func (cnf *Configurator) updateApResources(ingEx *IngressEx) (apRes AppProtectResources) {
12261225
if ingEx.AppProtectPolicy != nil {
12271226
policyFileName := appProtectPolicyFileNameFromUnstruct(ingEx.AppProtectPolicy)
12281227
policyContent := generateApResourceFileContent(ingEx.AppProtectPolicy)
12291228
cnf.nginxManager.CreateAppProtectResourceFile(policyFileName, policyContent)
1230-
apRes[appProtectPolicyKey] = policyFileName
1229+
apRes.AppProtectPolicy = policyFileName
12311230
}
12321231

12331232
if ingEx.AppProtectLogConf != nil {
1234-
logConfFileName := appProtectLogConfFileNameFromUnstruct(ingEx.AppProtectLogConf)
1235-
logConfContent := generateApResourceFileContent(ingEx.AppProtectLogConf)
1236-
cnf.nginxManager.CreateAppProtectResourceFile(logConfFileName, logConfContent)
1237-
apRes[appProtectLogConfKey] = logConfFileName + " " + ingEx.AppProtectLogDst
1233+
for i, logConf := range ingEx.AppProtectLogConf {
1234+
logConfFileName := appProtectLogConfFileNameFromUnstruct(logConf)
1235+
logConfContent := generateApResourceFileContent(logConf)
1236+
cnf.nginxManager.CreateAppProtectResourceFile(logConfFileName, logConfContent)
1237+
apRes.AppProtectLogconfs = append(apRes.AppProtectLogconfs, logConfFileName+" "+ingEx.AppProtectLogDst[i])
1238+
}
12381239
}
12391240

12401241
return apRes

internal/configs/configurator_test.go

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,19 +1079,20 @@ func TestUpdateApResources(t *testing.T) {
10791079
},
10801080
},
10811081
}
1082-
appProtectLogConf := &unstructured.Unstructured{
1083-
Object: map[string]interface{}{
1082+
appProtectLogConf := []*unstructured.Unstructured{
1083+
{Object: map[string]interface{}{
10841084
"metadata": map[string]interface{}{
10851085
"namespace": "test-ns",
10861086
"name": "test-name",
10871087
},
10881088
},
1089+
},
10891090
}
1090-
appProtectLogDst := "test-dst"
1091+
appProtectLogDst := []string{"test-dst"}
10911092

10921093
tests := []struct {
10931094
ingEx *IngressEx
1094-
expected map[string]string
1095+
expected AppProtectResources
10951096
msg string
10961097
}{
10971098
{
@@ -1100,7 +1101,7 @@ func TestUpdateApResources(t *testing.T) {
11001101
ObjectMeta: meta_v1.ObjectMeta{},
11011102
},
11021103
},
1103-
expected: map[string]string{},
1104+
expected: AppProtectResources{},
11041105
msg: "no app protect resources",
11051106
},
11061107
{
@@ -1110,8 +1111,8 @@ func TestUpdateApResources(t *testing.T) {
11101111
},
11111112
AppProtectPolicy: appProtectPolicy,
11121113
},
1113-
expected: map[string]string{
1114-
"policy": "/etc/nginx/waf/nac-policies/test-ns_test-name",
1114+
expected: AppProtectResources{
1115+
AppProtectPolicy: "/etc/nginx/waf/nac-policies/test-ns_test-name",
11151116
},
11161117
msg: "app protect policy",
11171118
},
@@ -1123,8 +1124,8 @@ func TestUpdateApResources(t *testing.T) {
11231124
AppProtectLogConf: appProtectLogConf,
11241125
AppProtectLogDst: appProtectLogDst,
11251126
},
1126-
expected: map[string]string{
1127-
"logconf": "/etc/nginx/waf/nac-logconfs/test-ns_test-name test-dst",
1127+
expected: AppProtectResources{
1128+
AppProtectLogconfs: []string{"/etc/nginx/waf/nac-logconfs/test-ns_test-name test-dst"},
11281129
},
11291130
msg: "app protect log conf",
11301131
},
@@ -1137,9 +1138,9 @@ func TestUpdateApResources(t *testing.T) {
11371138
AppProtectLogConf: appProtectLogConf,
11381139
AppProtectLogDst: appProtectLogDst,
11391140
},
1140-
expected: map[string]string{
1141-
"policy": "/etc/nginx/waf/nac-policies/test-ns_test-name",
1142-
"logconf": "/etc/nginx/waf/nac-logconfs/test-ns_test-name test-dst",
1141+
expected: AppProtectResources{
1142+
AppProtectPolicy: "/etc/nginx/waf/nac-policies/test-ns_test-name",
1143+
AppProtectLogconfs: []string{"/etc/nginx/waf/nac-logconfs/test-ns_test-name test-dst"},
11431144
},
11441145
msg: "app protect policy and log conf",
11451146
},

internal/configs/ingress.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ const emptyH 6D3F ost = ""
2020
const appProtectPolicyKey = "policy"
2121
const appProtectLogConfKey = "logconf"
2222

23+
// AppProtectResources holds namespace names of App Protect resources relavant to an Ingress
24+
type AppProtectResources struct {
25+
AppProtectPolicy string
26+
AppProtectLogconfs []string
27+
}
28+
2329
// IngressEx holds an Ingress along with the resources that are referenced in this Ingress.
2430
type IngressEx struct {
2531
Ingress *networking.Ingress
@@ -30,8 +36,8 @@ type IngressEx struct {
3036
ValidHosts map[string]bool
3137
ValidMinionPaths map[string]bool
3238
AppProtectPolicy *unstructured.Unstructured
33-
AppProtectLogConf *unstructured.Unstructured
34-
AppProtectLogDst string
39+
AppProtectLogConf []*unstructured.Unstructured
40+
AppProtectLogDst []string
3541
SecretRefs map[string]*secrets.SecretReference
3642
}
3743

@@ -55,7 +61,7 @@ type MergeableIngresses struct {
5561
Minions []*IngressEx
5662
}
5763

58-
func generateNginxCfg(ingEx *IngressEx, apResources map[string]string, isMinion bool, baseCfgParams *ConfigParams, isPlus bool,
64+
func generateNginxCfg(ingEx *IngressEx, apResources AppProtectResources, isMinion bool, baseCfgParams *ConfigParams, isPlus bool,
5965
isResolverConfigured bool, staticParams *StaticConfigParams, isWildcardEnabled bool) (version1.IngressNginxConfig, Warnings) {
6066
hasAppProtect := staticParams.MainAppProtectLoadModule
6167
cfgParams := parseAnnotations(ingEx, baseCfgParams, isPlus, hasAppProtect, staticParams.EnableInternalRoutes)
@@ -139,8 +145,8 @@ func generateNginxCfg(ingEx *IngressEx, apResources map[string]string, isMinion
139145
allWarnings.Add(warnings)
140146

141147
if hasAppProtect {
142-
server.AppProtectPolicy = apResources[appProtectPolicyKey]
143-
server.AppProtectLogConf = apResources[appProtectLogConfKey]
148+
server.AppProtectPolicy = apResources.AppProtectPolicy
149+
server.AppProtectLogConfs = apResources.AppProtectLogconfs
144150
}
145151

146152
if !isMinion && cfgParams.JWTKey != "" {
@@ -500,7 +506,7 @@ func upstreamMapToSlice(upstreams map[string]version1.Upstream) []version1.Upstr
500506
return result
501507
}
502508

503-
func generateNginxCfgForMergeableIngresses(mergeableIngs *MergeableIngresses, masterApResources map[string]string,
509+
func generateNginxCfgForMergeableIngresses(mergeableIngs *MergeableIngresses, masterApResources AppProtectResources,
504510
baseCfgParams *ConfigParams, isPlus bool, isResolverConfigured bool, staticParams *StaticConfigParams,
505511
isWildcardEnabled bool) (version1.IngressNginxConfig, Warnings) {
506512

@@ -558,8 +564,8 @@ func generateNginxCfgForMergeableIngresses(mergeableIngs *MergeableIngresses, ma
558564
}
559565

560566
isMinion := true
561-
// App Protect Resources not allowed in minions - pass empty map
562-
dummyApResources := make(map[string]string)
567+
// App Protect Resources not allowed in minions - pass empty struct
568+
dummyApResources := AppProtectResources{}
563569
nginxCfg, minionWarnings := generateNginxCfg(minion, dummyApResources, isMinion, baseCfgParams, isPlus, isResolverConfigured, staticParams, isWildcardEnabled)
564570
warnings.Add(minionWarnings)
565571

internal/configs/ingress_test.go

Lines changed: 28 additions & 26 deletions
< 38B3 /tr>
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ func TestGenerateNginxCfg(t *testing.T) {
2424
isPlus := false
2525
expected := createExpectedConfigForCafeIngressEx(isPlus)
2626

27-
apRes := make(map[string]string)
28-
result, warnings := generateNginxCfg(&cafeIngressEx, apRes, false, configParams, isPlus, false, &StaticConfigParams{}, false)
27+
apRes := AppProtectResources{}
28+
result, warnings := generateNginxCfg(&cafeIngressEx, apRes, false, configParams, false, false, &StaticConfigParams{}, false)
2929

3030
if diff := cmp.Diff(expected, result); diff != "" {
3131
t.Errorf("generateNginxCfg() returned unexpected result (-want +got):\n%s", diff)
@@ -66,8 +66,8 @@ func TestGenerateNginxCfgForJWT(t *testing.T) {
6666
},
6767
}
6868

69-
apRes := make(map[string]string)
70-
result, warnings := generateNginxCfg(&cafeIngressEx, apRes, false, configParams, isPlus, false, &StaticConfigParams{}, false)
69+
apRes := AppProtectResources{}
70+
result, warnings := generateNginxCfg(&cafeIngressEx, apRes, false, configParams, true, false, &StaticConfigParams{}, false)
7171

7272
if !reflect.DeepEqual(result.Servers[0].JWTAuth, expected.Servers[0].JWTAuth) {
7373
t.Errorf("generateNginxCfg returned \n%v, but expected \n%v", result.Servers[0].JWTAuth, expected.Servers[0].JWTAuth)
@@ -85,7 +85,7 @@ func TestGenerateNginxCfgWithMissingTLSSecret(t *testing.T) {
8585
cafeIngressEx.SecretRefs["cafe-secret"].Error = errors.New("secret doesn't exist")
8686
configParams := NewDefaultConfigParams()
8787

88-
apRes := make(map[string]string)
88+
apRes := AppProtectResources{}
8989
result, resultWarnings := generateNginxCfg(&cafeIngressEx, apRes, false, configParams, false, false, &StaticConfigParams{}, false)
9090

9191
expectedSSLRejectHandshake := true
@@ -109,7 +109,7 @@ func TestGenerateNginxCfgWithWildcardTLSSecret(t *testing.T) {
109109
cafeIngressEx.Ingress.Spec.TLS[0].SecretName = ""
110110
configParams := NewDefaultConfigParams()
111111

112-
apRes := make(map[string]string)
112+
apRes := AppProtectResources{}
113113
result, warnings := generateNginxCfg(&cafeIngressEx, apRes, false, configParams, false, false, &StaticConfigParams{}, true)
114114

115115
resultServer := result.Servers[0]
@@ -352,8 +352,8 @@ func TestGenerateNginxCfgForMergeableIngresses(t *testing.T) {
352352

353353
configParams := NewDefaultConfigParams()
354354

355-
masterApRes := make(map[string]string)
356-
result, warnings := generateNginxCfgForMergeableIngresses(mergeableIngresses, masterApRes, configParams, isPlus, false, &StaticConfigParams{}, false)
355+
masterApRes := AppProtectResources{}
356+
result, warnings := generateNginxCfgForMergeableIngresses(mergeableIngresses, masterApRes, configParams, false, false, &StaticConfigParams{}, false)
357357

358358
if diff := cmp.Diff(expected, result); diff != "" {
359359
t.Errorf("generateNginxCfgForMergeableIngresses() returned unexpected result (-want +got):\n%s", diff)
@@ -377,7 +377,7 @@ func TestGenerateNginxConfigForCrossNamespaceMergeableIngresses(t *testing.T) {
377377
expected := createExpectedConfigForCrossNamespaceMergeableCafeIngress()
378378
configParams := NewDefaultConfigParams()
379379

380-
emptyApResources := make(map[string]string)
380+
emptyApResources := AppProtectResources{}
381381
result, warnings := generateNginxCfgForMergeableIngresses(mergeableIngresses, emptyApResources, configParams, false, false, &StaticConfigParams{}, false)
382382

383383
if diff := cmp.Diff(expected, result); diff != "" {
@@ -442,7 +442,7 @@ func TestGenerateNginxCfgForMergeableIngressesForJWT(t *testing.T) {
442442
minionJwtKeyFileNames[objectMetaToFileName(&mergeableIngresses.Minions[0].Ingress.ObjectMeta)] = "/etc/nginx/secrets/default-coffee-jwk"
443443
configParams := NewDefaultConfigParams()
444444

445-
masterApRes := make(map[string]string)
445+
masterApRes := AppProtectResources{}
446446
result, warnings := generateNginxCfgForMergeableIngresses(mergeableIngresses, masterApRes, configParams, isPlus, false, &StaticConfigParams{}, false)
447447

448448
if !reflect.DeepEqual(result.Servers[0].JWTAuth, expected.Servers[0].JWTAuth) {
@@ -837,8 +837,8 @@ func TestGenerateNginxCfgForSpiffe(t *testing.T) {
837837
expected.Servers[0].Locations[i].SSL = true
838838
}
839839

840-
apResources := make(map[string]string)
841-
result, warnings := generateNginxCfg(&cafeIngressEx, apResources, false, configParams, isPlus, false,
840+
apResources := AppProtectResources{}
841+
result, warnings := generateNginxCfg(&cafeIngressEx, apResources, false, configParams, false, false,
842842
&StaticConfigParams{NginxServiceMesh: true}, false)
843843

844844
if diff := cmp.Diff(expected, result); diff != "" {
@@ -861,8 +861,8 @@ func TestGenerateNginxCfgForInternalRoute(t *testing.T) {
861861
expected.Servers[0].SpiffeCerts = true
862862
expected.Ingress.Annotations[internalRouteAnnotation] = "true"
863863

864-
apResources := make(map[string]string)
865-
result, warnings := generateNginxCfg(&cafeIngressEx, apResources, false, configParams, isPlus, false,
864+
apResources := AppProtectResources{}
865+
result, warnings := generateNginxCfg(&cafeIngressEx, apResources, false, configParams, false, false,
866866
&StaticConfigParams{NginxServiceMesh: true, EnableInternalRoutes: true}, false)
867867

868868
if diff := cmp.Diff(expected, result); diff != "" {
@@ -1311,19 +1311,20 @@ func TestGenerateNginxCfgForAppProtect(t *testing.T) {
13111311
},
13121312
},
13131313
}
1314-
cafeIngressEx.AppProtectLogConf = &unstructured.Unstructured{
1315-
Object: map[string]interface{}{
1314+
cafeIngressEx.AppProtectLogConf = []*unstructured.Unstructured{
1315+
{Object: map[string]interface{}{
13161316
"metadata": map[string]interface{}{
13171317
"namespace": "default",
13181318
"name": "logconf",
13191319
},
13201320
},
1321+
},
13211322
}
13221323

13231324
configParams := NewDefaultConfigParams()
1324-
apRes := map[string]string{
1325-
appProtectPolicyKey: "/etc/nginx/waf/nac-policies/default_dataguard-alarm",
1326-
appProtectLogConfKey: "/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514",
1325+
apRes := AppProtectResources{
1326+
AppProtectPolicy: "/etc/nginx/waf/nac-policies/default_dataguard-alarm",
1327+
AppProtectLogconfs: []string{"/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514"},
13271328
}
13281329
staticCfgParams := &StaticConfigParams{
13291330
MainAppProtectLoadModule: true,
@@ -1334,7 +1335,7 @@ func TestGenerateNginxCfgForAppProtect(t *testing.T) {
13341335
expected := createExpectedConfigForCafeIngressEx(isPlus)
13351336
expected.Servers[0].AppProtectEnable = "on"
13361337
expected.Servers[0].AppProtectPolicy = "/etc/nginx/waf/nac-policies/default_dataguard-alarm"
1337-
expected.Servers[0].AppProtectLogConf = "/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514"
1338+
expected.Servers[0].AppProtectLogConfs = []string{"/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514"}
13381339
expected.Servers[0].AppProtectLogEnable = "on"
13391340
expected.Ingress.Annotations = cafeIngressEx.Ingress.Annotations
13401341

@@ -1359,19 +1360,20 @@ func TestGenerateNginxCfgForMergeableIngressesForAppProtect(t *testing.T) {
13591360
},
13601361
},
13611362
}
1362-
mergeableIngresses.Master.AppProtectLogConf = &unstructured.Unstructured{
1363-
Object: map[string]interface{}{
1363+
mergeableIngresses.Master.AppProtectLogConf = []*unstructured.Unstructured{
1364+
{Object: map[string]interface{}{
13641365
"metadata": map[string]interface{}{
13651366
"namespace": "default",
13661367
"name": "logconf",
13671368
},
13681369
},
1370+
},
13691371
}
13701372

13711373
configParams := NewDefaultConfigParams()
1372-
apRes := map[string]string{
1373-
appProtectPolicyKey: "/etc/nginx/waf/nac-policies/default_dataguard-alarm",
1374-
appProtectLogConfKey: "/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514",
1374+
apRes := AppProtectResources{
1375+
AppProtectPolicy: "/etc/nginx/waf/nac-policies/default_dataguard-alarm",
1376+
AppProtectLogconfs: []string{"/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514"},
13751377
}
13761378
staticCfgParams := &StaticConfigParams{
13771379
MainAppProtectLoadModule: true,
@@ -1382,7 +1384,7 @@ func TestGenerateNginxCfgForMergeableIngressesForAppProtect(t *testing.T) {
13821384
expected := createExpectedConfigForMergeableCafeIngress(isPlus)
13831385
expected.Servers[0].AppProtectEnable = "on"
13841386
expected.Servers[0].AppProtectPolicy = "/etc/nginx/waf/nac-policies/default_dataguard-alarm"
1385-
expected.Servers[0].AppProtectLogConf = "/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514"
1387+
expected.Servers[0].AppProtectLogConfs = []string{"/etc/nginx/waf/nac-logconfs/default_logconf syslog:server=127.0.0.1:514"}
13861388
expected.Servers[0].AppProtectLogEnable = "on"
13871389
expected.Ingress.Annotations = mergeableIngresses.Master.Ingress.Annotations
13881390

internal/configs/version1/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ type Server struct {
9797
SSLPorts []int
9898
AppProtectEnable string
9999
AppProtectPolicy string
100-
AppProtectLogConf string
100+
AppProtectLogConfs []string
101101
AppProtectLogEnable string
102102

103103
SpiffeCerts bool

internal/configs/version1/nginx-plus.ingress.tmpl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ server {
7070
{{- end}}
7171
{{- if $server.AppProtectLogEnable}}
7272
app_protect_security_log_enable {{$server.AppProtectLogEnable}};
73-
{{if $server.AppProtectLogConf}}app_protect_security_log {{$server.AppProtectLogConf}};{{end}}
73+
{{if $server.AppProtectLogConfs}}{{range $AppProtectLogConf := $server.AppProtectLogConfs}}app_protect_security_log {{$AppProtectLogConf}};
74+
{{end}}{{end}}
7475
{{- end}}
7576

7677
{{if not $server.GRPCOnly}}

internal/k8s/appprotect/app_protect_resources.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ func ParseResourceReferenceAnnotation(ns, antn string) string {
118118
return antn
119119
}
120120

121+
// ParseResourceReferenceAnnotationList returns a slice of ns/names strings
122+
func ParseResourceReferenceAnnotationList(ns, annotations string) []string {
123+
out := []string{}
124+
for _, antn := range strings.Split(annotations, ",") {
125+
out = append(out, ParseResourceReferenceAnnotation(ns, antn))
126+
}
127+
return out
128+
}
129+
121130
func validateAppProtectUserSig(userSig *unstructured.Unstructured) error {
122131
sigName := userSig.GetName()
123132
err := validateRequiredSlices(userSig, appProtectUserSigRequiredSlices)

0 commit comments

Comments
 (0)
0