Skip to content

Commit

Permalink
Add support for header-based filtering on TrafficTargets
Browse files Browse the repository at this point in the history
  • Loading branch information
jspdown authored Aug 19, 2020
1 parent 21e0827 commit 64b9434
Show file tree
Hide file tree
Showing 12 changed files with 299 additions and 31 deletions.
8 changes: 4 additions & 4 deletions pkg/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ func (p *Provider) buildHTTPServicesAndRoutersForTrafficTarget(t *topology.Topol
}

func (p *Provider) buildTCPServicesAndRoutersForTrafficTarget(t *topology.Topology, tt *topology.ServiceTrafficTarget, cfg *dynamic.Configuration, ttSvc *topology.Service, ttKey topology.ServiceTrafficTargetKey) {
if !hasTrafficTargetSpecTCPRoute(tt) {
if !hasTrafficTargetRuleTCPRoute(tt) {
return
}

Expand Down Expand Up @@ -914,9 +914,9 @@ func buildUDPRouter(entrypoint string, svcKey string) *dynamic.UDPRouter {
}
}

func hasTrafficTargetSpecTCPRoute(tt *topology.ServiceTrafficTarget) bool {
for _, spec := range tt.Specs {
if spec.TCPRoute != nil {
func hasTrafficTargetRuleTCPRoute(tt *topology.ServiceTrafficTarget) bool {
for _, rule := range tt.Rules {
if rule.TCPRoute != nil {
return true
}
}
Expand Down
7 changes: 7 additions & 0 deletions pkg/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ func TestProvider_BuildConfig(t *testing.T) {
topology: "testdata/acl-enabled-tcp-basic-topology.json",
wantConfig: "testdata/acl-enabled-tcp-basic-config.json",
},
{
desc: "ACL enabled: HTTP service with http-route-group",
acl: true,
defaultTrafficType: "http",
topology: "testdata/acl-enabled-http-route-group-topology.json",
wantConfig: "testdata/acl-enabled-http-route-group-config.json",
},
{
desc: "ACL enabled: HTTP service with traffic-split",
acl: true,
Expand Down
21 changes: 19 additions & 2 deletions pkg/provider/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
func buildTrafficTargetRule(tt *topology.ServiceTrafficTarget) string {
var orRules []string

for _, spec := range tt.Specs {
for _, match := range spec.HTTPMatches {
for _, rule := range tt.Rules {
for _, match := range rule.HTTPMatches {
var matchParts []string

// Handle Path filtering.
Expand All @@ -21,6 +21,9 @@ func buildTrafficTargetRule(tt *topology.ServiceTrafficTarget) string {
// Handle Method filtering.
matchParts = appendMethodFilter(matchParts, match)

// Handle Header filtering.
matchParts = appendHeaderFilter(matchParts, match)

// Conditions within a HTTPMatch must all be fulfilled to be considered valid.
if len(matchParts) > 0 {
matchCond := strings.Join(matchParts, " && ")
Expand Down Expand Up @@ -72,6 +75,20 @@ func appendMethodFilter(matchParts []string, match *specs.HTTPMatch) []string {
return matchParts
}

func appendHeaderFilter(matchParts []string, match *specs.HTTPMatch) []string {
rules := make([]string, 0, len(match.Headers))

for name, value := range match.Headers {
rules = append(rules, fmt.Sprintf("HeadersRegexp(`%s`, `%s`)", name, value))
}

if len(rules) > 0 {
matchParts = append(matchParts, strings.Join(rules, " && "))
}

return matchParts
}

func buildHTTPRuleFromService(svc *topology.Service) string {
return fmt.Sprintf("Host(`%s.%s.maesh`) || Host(`%s`)", svc.Name, svc.Namespace, svc.ClusterIP)
}
Expand Down
78 changes: 78 additions & 0 deletions pkg/provider/testdata/acl-enabled-http-route-group-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
{
"http": {
"routers": {
"my-ns-svc-b-8080": {
"entryPoints": [
"http-10000"
],
"middlewares": [
"block-all-middleware"
],
"service": "block-all-service",
"rule": "Host(`svc-b.my-ns.maesh`) || Host(`10.10.14.1`)",
"priority": 1
},
"my-ns-svc-b-tt-8080-traffic-target-direct": {
"entryPoints": [
"http-10000"
],
"middlewares": [
"my-ns-svc-b-tt-whitelist-traffic-target-direct"
],
"service": "my-ns-svc-b-tt-8080-traffic-target",
"rule": "(Host(`svc-b.my-ns.maesh`) || Host(`10.10.14.1`)) && (PathPrefix(`/{path:app}`) || (PathPrefix(`/{path:api/notifications}`) && Method(`GET`)) || HeadersRegexp(`User-Agent`, `Mozilla/.*`))",
"priority": 2005
},
"readiness": {
"entryPoints": [
"readiness"
],
"service": "readiness",
"rule": "Path(`/ping`)"
}
},
"services": {
"block-all-service": {
"loadBalancer": {
"passHostHeader": false
}
},
"my-ns-svc-b-tt-8080-traffic-target": {
"loadBalancer": {
"servers": [
{
"url": "http://10.10.3.1:8080"
}
],
"passHostHeader": true
}
},
"readiness": {
"loadBalancer": {
"servers": [
{
"url": "http://127.0.0.1:8080"
}
],
"passHostHeader": true
}
}
},
"middlewares": {
"block-all-middleware": {
"ipWhiteList": {
"sourceRange": [
"255.255.255.255"
]
}
},
"my-ns-svc-b-tt-whitelist-traffic-target-direct": {
"ipWhiteList": {
"sourceRange": [
"10.10.2.1"
]
}
}
}
}
}
153 changes: 153 additions & 0 deletions pkg/provider/testdata/acl-enabled-http-route-group-topology.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
{
"services": {
"svc-b@my-ns": {
"name": "svc-b",
"namespace": "my-ns",
"selector": {},
"annotations": {},
"ports": [
{
"name": "port-8080",
"protocol": "TCP",
"port": 8080,
"targetPort": 8080
}
],
"clusterIp": "10.10.14.1",
"pods": [
"pod-b@my-ns"
],
"trafficTargets": [
"svc-b@my-ns:tt@my-ns"
]
}
},
"pods": {
"pod-a@my-ns": {
"name": "pod-a",
"namespace": "my-ns",
"serviceAccount": "client",
"ip": "10.10.2.1"
},
"pod-b@my-ns": {
"name": "pod-b",
"namespace": "my-ns",
"serviceAccount": "server",
"ip": "10.10.3.1",
"containerPorts": [
{
"name": "web",
"protocol": "TCP",
"containerPort": 8081
}
]
}
},
"serviceTrafficTargets": {
"svc-b@my-ns:tt@my-ns": {
"service": "svc-b@my-ns",
"name": "tt",
"namespace": "my-ns",
"sources": [
{
"serviceAccount": "client",
"namespace": "my-ns",
"pods": [
"pod-a@my-ns"
]
}
],
"destination": {
"serviceAccount": "server",
"namespace": "my-ns",
"ports": [
{
"name": "port-8080",
"protocol": "TCP",
"port": 8080,
"targetPort": 8080
}
],
"pods": [
"pod-b@my-ns"
]
},
"rules": [
{
"httpRouteGroup": {
"kind": "HTTPRouteGroup",
"apiVersion": "specs.smi-spec.io/v1alpha3",
"metadata": {
"name": "app-route-group",
"namespace": "my-ns"
},
"spec": {
"matches": [
{
"name": "app",
"methods": ["*"],
"pathRegex": "/app"
}
]
}
},
"httpMatches": [
{
"name": "app",
"methods": ["*"],
"pathRegex": "/app"
}
]
},
{
"httpRouteGroup": {
"kind": "HTTPRouteGroup",
"apiVersion": "specs.smi-spec.io/v1alpha3",
"metadata": {
"name": "app-route-group",
"namespace": "my-ns"
},
"spec": {
"matches": [
{
"name": "users",
"methods": ["GET", "POST", "PUT"],
"pathRegex": "/api/users"
},
{
"name": "notifications",
"methods": ["GET"],
"pathRegex": "/api/notifications"
},
{
"name": "firefox-beta",
"headers": [
{
"User-Agent": "Mozilla/.*"
}
]
}
]
}
},
"httpMatches": [
{
"name": "notifications",
"methods": ["GET"],
"pathRegex": "/api/notifications"
},
{
"name": "firefox-beta",
"headers": [
{
"User-Agent": "Mozilla/.*"
}
]
}
]
}
]
}
},
"trafficSplits": {}
}
2 changes: 1 addition & 1 deletion pkg/provider/testdata/acl-enabled-tcp-basic-topology.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"service": "svc-b@my-ns",
"name": "tt",
"namespace": "my-ns",
"specs": [
"rules": [
{
"tcpRoute": {
"kind": "TCPRoute",
Expand Down
4 changes: 2 additions & 2 deletions pkg/topology/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ func (b *Builder) evaluateTrafficTarget(res *resources, topology *Topology, tt *

var err error

stt.Specs, err = b.buildTrafficTargetSpecs(res, tt)
stt.Rules, err = b.buildTrafficTargetRules(res, tt)
if err != nil {
err = fmt.Errorf("unable to build spec: %v", err)
stt.AddError(err)
Expand Down Expand Up @@ -465,7 +465,7 @@ func (b *Builder) buildTrafficTargetSources(res *resources, t *Topology, tt *acc
return sources
}

func (b *Builder) buildTrafficTargetSpecs(res *resources, tt *access.TrafficTarget) ([]TrafficSpec, error) {
func (b *Builder) buildTrafficTargetRules(res *resources, tt *access.TrafficTarget) ([]TrafficSpec, error) {
var trafficSpecs []TrafficSpec

for _, s := range tt.Spec.Rules {
Expand Down
Loading

0 comments on commit 64b9434

Please sign in to comment.