Skip to content

Commit 180e04f

Browse files
authored
generate auth_jwt_claim_set directive (#7238)
1 parent 39f1068 commit 180e04f

File tree

12 files changed

+582
-35
lines changed

12 files changed

+582
-35
lines changed

config/crd/bases/k8s.nginx.org_policies.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,27 @@ spec:
179179
properties:
180180
burst:
181181
type: integer
182+
condition:
183+
description: RateLimitCondition defines a condition for a rate
184+
limit policy.
185+
properties:
186+
default:
187+
type: boolean
188+
jwt:
189+
description: JWTCondition defines a condition for a rate limit
190+
by JWT claim.
191+
properties:
192+
claim:
193+
pattern: ^([^$\s"'])*$
194+
type: string
195+
match:
196+
pattern: ^([^$\s."'])*$
197+
type: string
198+
required:
199+
- claim
200+
- match
201+
type: object
202+
type: object
182203
delay:
183204
type: integer
184205
dryRun:

deploy/crds.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,27 @@ spec:
341341
properties:
342342
burst:
343343
type: integer
344+
condition:
345+
description: RateLimitCondition defines a condition for a rate
346+
limit policy.
347+
properties:
348+
default:
349+
type: boolean
350+
jwt:
351+
description: JWTCondition defines a condition for a rate limit
352+
by JWT claim.
353+
properties:
354+
claim:
355+
pattern: ^([^$\s"'])*$
356+
type: string
357+
match:
358+
pattern: ^([^$\s."'])*$
359+
type: string
360+
required:
361+
- claim
362+
- match
363+
type: object
364+
type: object
344365
delay:
345366
type: integer
346367
dryRun:

internal/configs/version2/__snapshots__/templates_test.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2263,7 +2263,7 @@ server {
22632263

22642264
[TestExecuteVirtualServerTemplate_RendersTemplateWithRateLimitJWTClaim - 1]
22652265

2266-
auth_jwt_claim_set $jwt_default_webapp_group_consumer_group_type consumer_group type
2266+
auth_jwt_claim_set $jwt_default_webapp_group_consumer_group_type consumer_group type;
22672267
map $jwt_default_webapp_group_consumer_group_type $rate_limit_default_webapp_group_consumer_group_type {
22682268
default Group3;
22692269
Gold Group1;

internal/configs/version2/http.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type VirtualServerConfig struct {
1818
KeyVals []KeyVal
1919
LimitReqZones []LimitReqZone
2020
Maps []Map
21-
AuthJwtClaimSet []AuthJwtClaimSet
21+
AuthJWTClaimSets []AuthJWTClaimSet
2222
Server Server
2323
SpiffeCerts bool
2424
SpiffeClientCerts bool
@@ -29,10 +29,10 @@ type VirtualServerConfig struct {
2929
StaticSSLPath string
3030
}
3131

32-
// AuthJwtClaimSet defines the values for the `auth_jwt_claim_set` directive
33-
type AuthJwtClaimSet struct {
32+
// AuthJWTClaimSet defines the values for the `auth_jwt_claim_set` directive
33+
type AuthJWTClaimSet struct {
3434
Variable string
35-
Claims string
35+
Claim string
3636
}
3737

3838
// Upstream defines an upstream.

internal/configs/version2/nginx-plus.virtualserver.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ split_clients {{ $sc.Source }} {{ $sc.Variable }} {
5050
}
5151
{{- end }}
5252

53-
{{- range $claim := .AuthJwtClaimSet }}
54-
auth_jwt_claim_set {{ $claim.Variable }} {{ $claim.Claims}}
53+
{{- range $claim := .AuthJWTClaimSets }}
54+
auth_jwt_claim_set {{ $claim.Variable }} {{ $claim.Claim}};
5555
{{- end }}
5656

5757
{{- range $m := .Maps }}

internal/configs/version2/templates_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,10 +1574,10 @@ var (
15741574
},
15751575
},
15761576
Upstreams: []Upstream{},
1577-
AuthJwtClaimSet: []AuthJwtClaimSet{
1577+
AuthJWTClaimSets: []AuthJWTClaimSet{
15781578
{
15791579
Variable: "$jwt_default_webapp_group_consumer_group_type",
1580-
Claims: "consumer_group type",
1580+
Claim: "consumer_group type",
15811581
},
15821582
},
15831583
Maps: []Map{

internal/configs/virtualserver.go

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,12 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
453453
var statusMatches []version2.StatusMatch
454454
var healthChecks []version2.HealthCheck
455455
var limitReqZones []version2.LimitReqZone
456+
var authJWTClaimSets []version2.AuthJWTClaimSet
456457

457458
limitReqZones = append(limitReqZones, policiesCfg.RateLimit.Zones...)
458459

460+
authJWTClaimSets = append(authJWTClaimSets, policiesCfg.RateLimit.AuthJWTClaimSets...)
461+
459462
// generate upstreams for VirtualServer
460463
for _, u := range vsEx.VirtualServer.Spec.Upstreams {
461464

@@ -606,6 +609,8 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
606609
}
607610
limitReqZones = append(limitReqZones, routePoliciesCfg.RateLimit.Zones...)
608611

612+
authJWTClaimSets = append(authJWTClaimSets, routePoliciesCfg.RateLimit.AuthJWTClaimSets...)
613+
609614
dosRouteCfg := generateDosCfg(dosResources[r.Path])
610615

611616
if len(r.Matches) > 0 {
@@ -690,7 +695,7 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
690695
}
691696

692697
locSnippets := r.LocationSnippets
693-
// use the VirtualServer location snippet if the route does not define any
698+
// use the VirtualServer location snippet if the route does not define any
694699
if r.LocationSnippets == "" {
695700
locSnippets = vsrLocationSnippetsFromVs[vsrNamespaceName]
696701
}
@@ -747,6 +752,8 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
747752

748753
limitReqZones = append(limitReqZones, routePoliciesCfg.RateLimit.Zones...)
749754

755+
authJWTClaimSets = append(authJWTClaimSets, routePoliciesCfg.RateLimit.AuthJWTClaimSets...)
756+
750757
dosRouteCfg := generateDosCfg(dosResources[r.Path])
751758

752759
if len(r.Matches) > 0 {
@@ -828,12 +835,13 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
828835
})
829836

830837
vsCfg := version2.VirtualServerConfig{
831-
Upstreams: upstreams,
832-
SplitClients: splitClients,
833-
Maps: maps,
834-
StatusMatches: statusMatches,
835-
LimitReqZones: removeDuplicateLimitReqZones(limitReqZones),
836-
HTTPSnippets: httpSnippets,
838+
Upstreams: upstreams,
839+
SplitClients: splitClients,
840+
Maps: maps,
841+
StatusMatches: statusMatches,
842+
LimitReqZones: removeDuplicateLimitReqZones(limitReqZones),
843+
AuthJWTClaimSets: removeDuplicateAuthJWTClaimSets(authJWTClaimSets),
844+
HTTPSnippets: httpSnippets,
837845
Server: version2.Server{
838846
ServerName: vsEx.VirtualServer.Spec.Host,
839847
Gunzip: vsEx.VirtualServer.Spec.Gunzip,
@@ -893,9 +901,10 @@ func (vsc *virtualServerConfigurator) GenerateVirtualServerConfig(
893901

894902
// rateLimit hold the configuration for the ratelimiting Policy
895903
type rateLimit struct {
896-
Reqs []version2.LimitReq
897-
Zones []version2.LimitReqZone
898-
Options version2.LimitReqOptions
904+
Reqs []version2.LimitReq
905+
Zones []version2.LimitReqZone
906+
Options version2.LimitReqOptions
907+
AuthJWTClaimSets []version2.AuthJWTClaimSet
899908
}
900909

901910
// jwtAuth hold the configuration for the JWTAuth & JWKSAuth Policies
@@ -1011,6 +1020,9 @@ func (p *policiesCfg) addRateLimitConfig(
10111020
rlZoneName := fmt.Sprintf("pol_rl_%v_%v_%v_%v", polNamespace, polName, vsNamespace, vsName)
10121021
p.RateLimit.Reqs = append(p.RateLimit.Reqs, generateLimitReq(rlZoneName, rateLimit))
10131022
p.RateLimit.Zones = append(p.RateLimit.Zones, generateLimitReqZone(rlZoneName, rateLimit, podReplicas))
1023+
if rateLimit.Condition != nil && rateLimit.Condition.JWT.Claim != "" && rateLimit.Condition.JWT.Match != "" {
1024+
p.RateLimit.AuthJWTClaimSets = append(p.RateLimit.AuthJWTClaimSets, generateAuthJwtClaimSet(*rateLimit.Condition.JWT, vsNamespace, vsName))
1025+
}
10141026
if len(p.RateLimit.Reqs) == 1 {
10151027
p.RateLimit.Options = generateLimitReqOptions(rateLimit)
10161028
} else {
@@ -1667,6 +1679,35 @@ func removeDuplicateLimitReqZones(rlz []version2.LimitReqZone) []version2.LimitR
16671679
return result
16681680
}
16691681

1682+
func removeDuplicateAuthJWTClaimSets(ajcs []version2.AuthJWTClaimSet) []version2.AuthJWTClaimSet {
1683+
encountered := make(map[string]bool)
1684+
var result []version2.AuthJWTClaimSet
1685+
1686+
for _, v := range ajcs {
1687+
if !encountered[v.Variable] {
1688+
encountered[v.Variable] = true
1689+
result = append(result, v)
1690+
}
1691+
}
1692+
1693+
return result
1694+
}
1695+
1696+
func generateAuthJwtClaimSet(jwtCondition conf_v1.JWTCondition, vsNamespace string, vsName string) version2.AuthJWTClaimSet {
1697+
return version2.AuthJWTClaimSet{
1698+
Variable: generateAuthJwtClaimSetVariable(jwtCondition.Claim, vsNamespace, vsName),
1699+
Claim: generateAuthJwtClaimSetClaim(jwtCondition.Claim),
1700+
}
1701+
}
1702+
1703+
func generateAuthJwtClaimSetVariable(claim string, vsNamespace string, vsName string) string {
1704+
return fmt.Sprintf("$jwt_%v_%v_%v", vsNamespace, vsName, strings.Join(strings.Split(claim, "."), "_"))
1705+
}
1706+
1707+
func generateAuthJwtClaimSetClaim(claim string) string {
1708+
return strings.Join(strings.Split(claim, "."), " ")
1709+
}
1710+
16701711
func addPoliciesCfgToLocation(cfg policiesCfg, location *version2.Location) {
16711712
location.Allow = cfg.Allow
16721713
location.Deny = cfg.Deny

0 commit comments

Comments
 (0)