mirror of
https://github.com/zitadel/zitadel.git
synced 2024-12-13 11:34:26 +00:00
7508e6c9f3
# Which Problems Are Solved
System administrators can block hosts and IPs for HTTP calls in actions.
Using DNS, blocked IPs could be bypassed.
# How the Problems Are Solved
- Hosts are resolved (DNS lookup) to check whether their corresponding
IP is blocked.
# Additional Changes
- Added complete lookup ip address range and "unspecified" address to
the default `DenyList`
(cherry picked from commit 79fb4cc1cc
)
95 lines
1.8 KiB
Go
95 lines
1.8 KiB
Go
package actions
|
|
|
|
import (
|
|
"net"
|
|
"reflect"
|
|
"strings"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
)
|
|
|
|
func SetHTTPConfig(config *HTTPConfig) {
|
|
httpConfig = config
|
|
}
|
|
|
|
var httpConfig *HTTPConfig
|
|
|
|
type HTTPConfig struct {
|
|
DenyList []AddressChecker
|
|
}
|
|
|
|
func HTTPConfigDecodeHook(from, to reflect.Value) (interface{}, error) {
|
|
if to.Type() != reflect.TypeOf(HTTPConfig{}) {
|
|
return from.Interface(), nil
|
|
}
|
|
|
|
config := struct {
|
|
DenyList []string
|
|
}{}
|
|
|
|
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
|
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
|
|
WeaklyTypedInput: true,
|
|
Result: &config,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if err = decoder.Decode(from.Interface()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
c := HTTPConfig{
|
|
DenyList: make([]AddressChecker, 0),
|
|
}
|
|
|
|
for _, unsplit := range config.DenyList {
|
|
for _, split := range strings.Split(unsplit, ",") {
|
|
parsed, parseErr := NewHostChecker(split)
|
|
if parseErr != nil {
|
|
return nil, parseErr
|
|
}
|
|
if parsed != nil {
|
|
c.DenyList = append(c.DenyList, parsed)
|
|
}
|
|
}
|
|
}
|
|
|
|
return c, nil
|
|
}
|
|
|
|
func NewHostChecker(entry string) (AddressChecker, error) {
|
|
_, network, err := net.ParseCIDR(entry)
|
|
if err == nil {
|
|
return &HostChecker{Net: network}, nil
|
|
}
|
|
if ip := net.ParseIP(entry); ip != nil {
|
|
return &HostChecker{IP: ip}, nil
|
|
}
|
|
return &HostChecker{Domain: entry}, nil
|
|
}
|
|
|
|
type HostChecker struct {
|
|
Net *net.IPNet
|
|
IP net.IP
|
|
Domain string
|
|
}
|
|
|
|
func (c *HostChecker) Matches(ips []net.IP, address string) bool {
|
|
// if the address matches the domain, no additional checks as needed
|
|
if c.Domain == address {
|
|
return true
|
|
}
|
|
// otherwise we need to check on ips (incl. the resolved ips of the host)
|
|
for _, ip := range ips {
|
|
if c.Net != nil && c.Net.Contains(ip) {
|
|
return true
|
|
}
|
|
if c.IP != nil && c.IP.Equal(ip) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|