Skip to content

Commit

Permalink
Merge branch 'master' of github.com:in4it/roxprox
Browse files Browse the repository at this point in the history
  • Loading branch information
wardviaene committed Sep 24, 2019
2 parents 892bf58 + c16fa65 commit 91008f6
Show file tree
Hide file tree
Showing 10 changed files with 330 additions and 93 deletions.
8 changes: 7 additions & 1 deletion pkg/api/rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,15 @@ type RuleConditions struct {
Methods []string `json:"methods"`
}
type RuleActions struct {
Proxy RuleActionsProxy `json:"proxy"`
Proxy RuleActionsProxy `json:"proxy"`
DirectResponse RuleActionsDirectResponse `json:"directResponse" yaml:"directResponse"`
}
type RuleActionsProxy struct {
Hostname string `json:"hostname"`
Port int64 `json:"port"`
}

type RuleActionsDirectResponse struct {
Status uint32 `json:"status"`
Body string `json:"body"`
}
124 changes: 101 additions & 23 deletions pkg/envoy/listener.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package envoy

import (
"fmt"
"reflect"
"sort"
"strings"

Expand Down Expand Up @@ -150,9 +151,10 @@ func (l *Listener) getListenerRouteSpecifier(manager hcm.HttpConnectionManager)
return routeSpecifier, nil
}

func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, clusterName, virtualHostName string, methods []string, matchType string) *route.VirtualHost {
func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, clusterName, virtualHostName string, methods []string, matchType string, directResponse DirectResponse) *route.VirtualHost {
var hostRewriteSpecifier *route.RouteAction_HostRewrite
var routes []*route.Route
var routeAction *route.Route_Route

if hostname == "" {
hostname = "*"
Expand All @@ -162,15 +164,16 @@ func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, cluste
hostRewriteSpecifier = &route.RouteAction_HostRewrite{
HostRewrite: targetHostname,
}
}

routeAction := &route.Route_Route{
Route: &route.RouteAction{
HostRewriteSpecifier: hostRewriteSpecifier,
ClusterSpecifier: &route.RouteAction_Cluster{
Cluster: clusterName,
routeAction = &route.Route_Route{
Route: &route.RouteAction{
HostRewriteSpecifier: hostRewriteSpecifier,
ClusterSpecifier: &route.RouteAction_Cluster{
Cluster: clusterName,
},
},
},
}
} else {
routeAction = &route.Route_Route{}
}

var headers []*route.HeaderMatcher
Expand All @@ -185,7 +188,8 @@ func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, cluste
})
}
}
if matchType == "prefix" {
switch matchType {
case "prefix":
if len(headers) == 0 {
routes = append(routes, &route.Route{
Match: &route.RouteMatch{
Expand All @@ -208,7 +212,7 @@ func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, cluste
})
}
}
} else if matchType == "path" {
case "path":
if len(headers) == 0 {
routes = append(routes, &route.Route{
Match: &route.RouteMatch{
Expand All @@ -231,7 +235,7 @@ func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, cluste
})
}
}
} else if matchType == "regex" {
case "regex":
if len(headers) == 0 {
routes = append(routes, &route.Route{
Match: &route.RouteMatch{
Expand All @@ -256,6 +260,22 @@ func (l *Listener) getVirtualHost(hostname, targetHostname, targetPrefix, cluste
}
}

// fill out directresponse action if defined
if directResponse.Status > 0 {
for routeKey := range routes {
routes[routeKey].Action = &route.Route_DirectResponse{
DirectResponse: &route.DirectResponseAction{
Status: directResponse.Status,
Body: &core.DataSource{
Specifier: &core.DataSource_InlineString{
InlineString: directResponse.Body,
},
},
},
}
}
}

return &route.VirtualHost{
Name: virtualHostName,
Domains: []string{hostname},
Expand Down Expand Up @@ -341,7 +361,7 @@ func (l *Listener) updateListener(cache *WorkQueueCache, params ListenerParams,
}

// create new virtualhost
v := l.getVirtualHost(params.Conditions.Hostname, params.TargetHostname, targetPrefix, params.Name, virtualHostname, params.Conditions.Methods, matchType)
v := l.getVirtualHost(params.Conditions.Hostname, params.TargetHostname, targetPrefix, params.Name, virtualHostname, params.Conditions.Methods, matchType, params.DirectResponse)

// check if we need to overwrite the virtualhost
virtualHostKey := -1
Expand Down Expand Up @@ -541,7 +561,7 @@ func (l *Listener) DeleteRoute(cache *WorkQueueCache, params ListenerParams, par
return err
}

v := l.getVirtualHost(params.Conditions.Hostname, params.TargetHostname, targetPrefix, params.Name, virtualHostname, params.Conditions.Methods, matchType)
v := l.getVirtualHost(params.Conditions.Hostname, params.TargetHostname, targetPrefix, params.Name, virtualHostname, params.Conditions.Methods, matchType, params.DirectResponse)

virtualHostKey := -1
for k, curVirtualHost := range routeSpecifier.RouteConfig.VirtualHosts {
Expand Down Expand Up @@ -604,17 +624,28 @@ func (l *Listener) validateListeners(listeners []cache.Resource, clusterNames []
}
for _, virtualHost := range routeSpecifier.RouteConfig.VirtualHosts {
for _, virtualHostRoute := range virtualHost.Routes {
clusterFound := false
virtualHostRouteClusterName := virtualHostRoute.Action.(*route.Route_Route).Route.ClusterSpecifier.(*route.RouteAction_Cluster).Cluster
for _, clusterName := range clusterNames {
if clusterName == virtualHostRouteClusterName {
clusterFound = true
if virtualHostRoute.Action != nil {
switch reflect.TypeOf(virtualHostRoute.Action).String() {
case "*route.Route_Route":
clusterFound := false
virtualHostRouteClusterName := virtualHostRoute.Action.(*route.Route_Route).Route.ClusterSpecifier.(*route.RouteAction_Cluster).Cluster
for _, clusterName := range clusterNames {
if clusterName == virtualHostRouteClusterName {
clusterFound = true
}
}
if !clusterFound {
return false, fmt.Errorf("Cluster not found: %s", virtualHostRouteClusterName)
}
case "*route.Route_DirectResponse":
logger.Debugf("Validation: DirectResponse, no cluster validation necessary")
// no validation necessary
default:
return false, fmt.Errorf("Route action type is unknown: %s", reflect.TypeOf(virtualHostRoute.Action).String())
}
} else {
return false, fmt.Errorf("Validation: no route action found for virtualhost: %+v", virtualHost)
}
if !clusterFound {
return false, fmt.Errorf("Cluster not found: %s", virtualHostRouteClusterName)
}

}
}
}
Expand All @@ -636,3 +667,50 @@ func (l *Listener) updateDefaultTracingSetting(tracing TracingParams) {
func (l *Listener) newHTTPRouterFilter() []*hcm.HttpFilter {
return l.httpFilter
}

func (l *Listener) printListener(cache *WorkQueueCache) (string, error) {
var res string
for _, listener := range cache.listeners {
ll := listener.(*api.Listener)
res += "Listener: " + ll.Name + "\n"
manager, err := getListenerHTTPConnectionManager(ll)
if err != nil {
return "", err
}
routeSpecifier, err := l.getListenerRouteSpecifier(manager)
if err != nil {
return "", err
}
for _, virtualHost := range routeSpecifier.RouteConfig.VirtualHosts {
res += "Virtualhost: " + virtualHost.GetName() + "\n"
for _, virtualHostRoute := range virtualHost.Routes {
if virtualHostRoute.Match != nil {
if virtualHostRoute.Match.GetPath() != "" {
res += "Match path: " + virtualHostRoute.Match.GetPath() + "\n"
}
if virtualHostRoute.Match.GetPrefix() != "" {
res += "Match prefix: " + virtualHostRoute.Match.GetPrefix() + "\n"
}
if virtualHostRoute.Match.GetRegex() != "" {
res += "Match regex: " + virtualHostRoute.Match.GetRegex() + "\n"
}
}
if virtualHostRoute.Action != nil {
switch reflect.TypeOf(virtualHostRoute.Action).String() {
case "*route.Route_Route":
res += "Route action (cluster): " + virtualHostRoute.Action.(*route.Route_Route).Route.ClusterSpecifier.(*route.RouteAction_Cluster).Cluster + "\n"
case "*route.Route_DirectResponse":
res += "Route action (directResponse): "
res += fmt.Sprint(virtualHostRoute.Action.(*route.Route_DirectResponse).DirectResponse.GetStatus()) + " "
res += virtualHostRoute.Action.(*route.Route_DirectResponse).DirectResponse.Body.GetInlineString() + "\n"
default:
return "", fmt.Errorf("Route action type is unknown: %s", reflect.TypeOf(virtualHostRoute.Action).String())
}
} else {
return "", fmt.Errorf("Validation: no route action found for virtualhost: %+v", virtualHost)
}
}
}
}
return res, nil
}
39 changes: 39 additions & 0 deletions pkg/envoy/listener_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,17 @@ func TestUpdateListener(t *testing.T) {
FailureModeAllow: false,
},
}
params10 := ListenerParams{
Name: "directResponseTest",
Conditions: Conditions{
Path: "/directresponse",
Methods: []string{"GET"},
},
DirectResponse: DirectResponse{
Status: 200,
Body: "OK",
},
}

listener := l.createListener(params1, paramsTLS1)
cache.listeners = append(cache.listeners, listener)
Expand Down Expand Up @@ -498,7 +509,17 @@ func TestUpdateListener(t *testing.T) {
if err := validateNewHTTPRouterFilter(l.newHTTPRouterFilter(), params9); err != nil {
t.Errorf("Validation failed: %s", err)
return
}

// update listener with domain 10
if err := l.updateListener(&cache, params10, paramsTLS1); err != nil {
t.Errorf("Error: %s", err)
return
}
// validate domain 10
if err := validateDomain(cache.listeners, params10); err != nil {
t.Errorf("Validation failed: %s", err)
return
}
}

Expand Down Expand Up @@ -661,6 +682,7 @@ func validateAttributes(manager hcm.HttpConnectionManager, params ListenerParams
prefixFound := false
pathFound := false
regexFound := false
directResponseFound := false
methodsFound := make(map[string]bool)

if params.Conditions.Hostname == "" {
Expand Down Expand Up @@ -701,6 +723,17 @@ func validateAttributes(manager hcm.HttpConnectionManager, params ListenerParams
}
}
}
switch reflect.TypeOf(r.Action).String() {
case "*route.Route_Route":
// do nothing here
case "*route.Route_DirectResponse":
d := r.Action.(*route.Route_DirectResponse).DirectResponse
if params.DirectResponse.Status == d.GetStatus() && params.DirectResponse.Body == d.GetBody().GetInlineString() {
directResponseFound = true
}
default:
return fmt.Errorf("Type is %s", reflect.TypeOf(r.Action).String())
}
}
}
}
Expand Down Expand Up @@ -737,6 +770,12 @@ func validateAttributes(manager hcm.HttpConnectionManager, params ListenerParams
logger.Debugf("Methods found: %s", strings.Join(params.Conditions.Methods, ","))
}

if params.DirectResponse.Status > 0 && !directResponseFound {
return fmt.Errorf("Got directresponse parameter, but no directresponse found")
} else {
logger.Debugf("Directresponse found found: %d : %s", params.DirectResponse.Status, params.DirectResponse.Body)
}

return validateJWT(manager, params)

}
Expand Down
11 changes: 11 additions & 0 deletions pkg/envoy/testdata/test-directresponse.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
api: proxy.in4it.io/v1
kind: rule
metadata:
name: healthcheck
spec:
conditions:
- path: /.roxprox/health
actions:
- directResponse:
status: 200
body: "OK"
17 changes: 14 additions & 3 deletions pkg/envoy/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ type ListenerParams struct {
Conditions Conditions
Auth Auth
Authz Authz
DirectResponse DirectResponse
}

type ChallengeParams struct {
Expand Down Expand Up @@ -77,9 +78,10 @@ type Auth struct {
}

type Action struct {
RuleName string
Type string
Proxy ActionProxy
RuleName string
Type string
Proxy ActionProxy
DirectResponse DirectResponseAction
}

type ActionProxy struct {
Expand All @@ -101,3 +103,12 @@ type TracingParams struct {
RandomSampling float64
OverallSampling float64
}

type DirectResponse struct {
Status uint32
Body string
}
type DirectResponseAction struct {
Status uint32
Body string
}
13 changes: 13 additions & 0 deletions pkg/envoy/workqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ func (w *WorkQueue) Submit(items []WorkQueueItem) (string, error) {
for k, item := range items {
itemID := uuid.New().String()
items[k].id = itemID
logger.Tracef("WorkQueue: processing item: %s", item.Action)
switch item.Action {
case "createCluster":
if element, err := w.cluster.findCluster(w.cache.clusters, item.ClusterParams); err == nil {
Expand Down Expand Up @@ -115,6 +116,18 @@ func (w *WorkQueue) Submit(items []WorkQueueItem) (string, error) {
}
updateXds = true
}
case "createRuleWithoutCluster":
if len(w.cache.listeners) == 0 {
w.cache.listeners = append(w.cache.listeners, w.listener.createListener(item.ListenerParams, item.TLSParams))
}
err := w.listener.updateListener(&w.cache, item.ListenerParams, item.TLSParams)
if err != nil {
logger.Errorf("createRule error: %s", err)
item.state = "error"
} else {
item.state = "finished"
}
updateXds = true
case "createJwtRule":
err := w.jwtProvider.UpdateJwtRule(&w.cache, item.ListenerParams, item.TLSParams)
if err != nil {
Expand Down
Loading

0 comments on commit 91008f6

Please sign in to comment.