Skip to content

Commit

Permalink
refactor: allow overrides for allow/blocks on namespace annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
shreddedbacon committed Dec 14, 2023
1 parent d2dbda0 commit 75c5804
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 13 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ It is possible to add global IP allow and block lists, the helm chart will have
* allowing IP addresses via `/lists/allowedips` file which is a single line per entry of ip address to allow
* blocking IP addresses via `/lists/blockedips` file which is a single line per entry of ip address to block

There are also annotations that can be added to specific `Kind: Ingress` objects that allow for ip allow or blocking.
There are also annotations that can be added to the namespace, or individual `Kind: Ingress` objects that allow for ip allow or blocking.
* `idling.amazee.io/ip-allow-list` - a comma separated list of ip addresses to allow, will be checked against x-forward-for, but if true-client-ip is provided it will prefer this.
* `idling.amazee.io/ip-block-list` - a comma separated list of ip addresses to allow, will be checked against x-forward-for, but if true-client-ip is provided it will prefer this.

Expand All @@ -40,7 +40,7 @@ It is possible to add global UserAgent allow and block lists, the helm chart wil
* allowing user agents via a `/lists/allowedagents` file which is a single line per entry of useragents or regex patterns to match against. These must be `go` based regular expressions.
* blocking user agents via a `/lists/blockedagents` file which is a single line per entry of useragents or regex patterns to match against. These must be `go` based regular expressions.

There are also annotations that can be added to specific `Kind: Ingress` objects that allow for user agent allow or blocking.
There are also annotations that can be added to the namespace, or individual `Kind: Ingress` objects that allow for user agent allow or blocking.
* `idling.amazee.io/allowed-agents` - a comma separated list of user agents or regex patterns to allow.
* `idling.amazee.io/blocked-agents` - a comma separated list of user agents or regex patterns to block.

Expand Down
10 changes: 9 additions & 1 deletion handlers/unidler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"time"

"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
networkv1 "k8s.io/api/networking/v1"
"k8s.io/apimachinery/pkg/types"
)
Expand Down Expand Up @@ -66,6 +67,13 @@ func (h *Unidler) ingressHandler(path string) func(http.ResponseWriter, *http.Re
// @TODO: check for code 503 specifically, or just any request that has the namespace in it will be "unidled" if a request comes in for
// that ingress and the
if ns != "" {
namespace := &corev1.Namespace{}
if err := h.Client.Get(ctx, types.NamespacedName{
Name: ns,
}, namespace); err != nil {
opLog.Info(fmt.Sprintf("unable to get any namespaces: %v", err))
return
}
ingress := &networkv1.Ingress{}
if err := h.Client.Get(ctx, types.NamespacedName{
Namespace: ns,
Expand All @@ -81,7 +89,7 @@ func (h *Unidler) ingressHandler(path string) func(http.ResponseWriter, *http.Re
trueClientIP := r.Header.Get("True-Client-IP")
requestUserAgent := r.Header.Get("User-Agent")

allowUnidle := h.checkAccess(ingress.ObjectMeta.Annotations, requestUserAgent, trueClientIP, xForwardedFor)
allowUnidle := h.checkAccess(namespace.ObjectMeta.Annotations, ingress.ObjectMeta.Annotations, requestUserAgent, trueClientIP, xForwardedFor)
// then run checks to start to unidle the environment
if allowUnidle {
// if a namespace exists, it means that the custom-http-errors code is defined in the ingress object
Expand Down
38 changes: 29 additions & 9 deletions handlers/unidler/restrictions.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ func checkIPList(allowList []string, xForwardedFor []string, trueClientIP string
return false
}

func (h *Unidler) checkAccess(annotations map[string]string, userAgent, trueClientIP string, xForwardedFor []string) bool {
func (h *Unidler) checkAccess(nsannotations map[string]string, annotations map[string]string, userAgent, trueClientIP string, xForwardedFor []string) bool {
allowedIP := false
allowedAgent := false
blockedIP := false
Expand All @@ -51,9 +51,14 @@ func (h *Unidler) checkAccess(annotations map[string]string, userAgent, trueClie
hasIPAllowList = true
allowedIP = checkIPList(strings.Split(alist, ","), xForwardedFor, trueClientIP)
} else {
if h.AllowedIPs != nil {
if alist, ok := nsannotations["idling.amazee.io/ip-allow-list"]; ok {
hasIPAllowList = true
allowedIP = checkIPList(h.AllowedIPs, xForwardedFor, trueClientIP)
allowedIP = checkIPList(strings.Split(alist, ","), xForwardedFor, trueClientIP)
} else {
if h.AllowedIPs != nil {
hasIPAllowList = true
allowedIP = checkIPList(h.AllowedIPs, xForwardedFor, trueClientIP)
}
}
}

Expand All @@ -63,9 +68,14 @@ func (h *Unidler) checkAccess(annotations map[string]string, userAgent, trueClie
hasIPBlockList = true
blockedIP = checkIPList(strings.Split(blist, ","), xForwardedFor, trueClientIP)
} else {
if h.BlockedIPs != nil {
if blist, ok := nsannotations["idling.amazee.io/ip-block-list"]; ok {
hasIPBlockList = true
blockedIP = checkIPList(h.BlockedIPs, xForwardedFor, trueClientIP)
blockedIP = checkIPList(strings.Split(blist, ","), xForwardedFor, trueClientIP)
} else {
if h.BlockedIPs != nil {
hasIPBlockList = true
blockedIP = checkIPList(h.BlockedIPs, xForwardedFor, trueClientIP)
}
}
}

Expand All @@ -81,19 +91,29 @@ func (h *Unidler) checkAccess(annotations map[string]string, userAgent, trueClie
hasAllowedAgentList = true
allowedAgent = checkAgents(strings.Split(agents, ","), userAgent)
} else {
if h.AllowedUserAgents != nil {
if agents, ok := annotations["idling.amazee.io/allowed-agents"]; ok {
hasAllowedAgentList = true
allowedAgent = checkAgents(h.AllowedUserAgents, userAgent)
allowedAgent = checkAgents(strings.Split(agents, ","), userAgent)
} else {
if h.AllowedUserAgents != nil {
hasAllowedAgentList = true
allowedAgent = checkAgents(h.AllowedUserAgents, userAgent)
}
}
}

if agents, ok := annotations["idling.amazee.io/blocked-agents"]; ok {
hasBlockedAgentList = true
blockedAgent = checkAgents(strings.Split(agents, ","), userAgent)
} else {
if h.BlockedUserAgents != nil {
if agents, ok := annotations["idling.amazee.io/blocked-agents"]; ok {
hasBlockedAgentList = true
blockedAgent = checkAgents(h.BlockedUserAgents, userAgent)
blockedAgent = checkAgents(strings.Split(agents, ","), userAgent)
} else {
if h.BlockedUserAgents != nil {
hasBlockedAgentList = true
blockedAgent = checkAgents(h.BlockedUserAgents, userAgent)
}
}
}

Expand Down
22 changes: 21 additions & 1 deletion handlers/unidler/restrictions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func TestUnidler_checkAccess(t *testing.T) {
BlockedIPs []string
}
type args struct {
nsannotations map[string]string
annotations map[string]string
userAgent string
trueClientIP string
Expand Down Expand Up @@ -362,6 +363,25 @@ func TestUnidler_checkAccess(t *testing.T) {
},
want: true,
},
{
name: "test15 - allowed ip blocked agent namespace annotation",
args: args{
nsannotations: map[string]string{
"idling.amazee.io/blocked-agents": "@(example).test.?$,@(internal).test.?$",
"idling.amazee.io/ip-allow-list": "1.2.3.4",
},
userAgent: "This is not a bot, don't complaint to: [email protected].",
trueClientIP: "1.2.3.4",
xForwardedFor: nil,
},
fields: fields{
AllowedUserAgents: nil,
BlockedUserAgents: nil,
BlockedIPs: nil,
AllowedIPs: nil,
},
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -371,7 +391,7 @@ func TestUnidler_checkAccess(t *testing.T) {
AllowedIPs: tt.fields.AllowedIPs,
BlockedIPs: tt.fields.BlockedIPs,
}
if got := h.checkAccess(tt.args.annotations, tt.args.userAgent, tt.args.trueClientIP, tt.args.xForwardedFor); got != tt.want {
if got := h.checkAccess(tt.args.nsannotations, tt.args.annotations, tt.args.userAgent, tt.args.trueClientIP, tt.args.xForwardedFor); got != tt.want {
t.Errorf("Unidler.checkAccess() = %v, want %v", got, tt.want)
}
})
Expand Down

0 comments on commit 75c5804

Please sign in to comment.