2017-10-10 12:50:03 +00:00
|
|
|
package whitelist
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
// IP allows to check that addresses are in a white list
|
|
|
|
type IP struct {
|
|
|
|
whiteListsIPs []*net.IP
|
|
|
|
whiteListsNet []*net.IPNet
|
2017-10-16 10:46:03 +00:00
|
|
|
insecure bool
|
2017-10-10 12:50:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewIP builds a new IP given a list of CIDR-Strings to whitelist
|
2017-10-16 10:46:03 +00:00
|
|
|
func NewIP(whitelistStrings []string, insecure bool) (*IP, error) {
|
|
|
|
if len(whitelistStrings) == 0 && !insecure {
|
2017-10-10 12:50:03 +00:00
|
|
|
return nil, errors.New("no whiteListsNet provided")
|
|
|
|
}
|
|
|
|
|
|
|
|
ip := IP{}
|
|
|
|
|
2017-10-16 10:46:03 +00:00
|
|
|
if !insecure {
|
|
|
|
for _, whitelistString := range whitelistStrings {
|
|
|
|
ipAddr := net.ParseIP(whitelistString)
|
|
|
|
if ipAddr != nil {
|
|
|
|
ip.whiteListsIPs = append(ip.whiteListsIPs, &ipAddr)
|
|
|
|
} else {
|
|
|
|
_, whitelist, err := net.ParseCIDR(whitelistString)
|
|
|
|
if err != nil {
|
|
|
|
return nil, fmt.Errorf("parsing CIDR whitelist %s: %v", whitelist, err)
|
|
|
|
}
|
|
|
|
ip.whiteListsNet = append(ip.whiteListsNet, whitelist)
|
2017-10-10 12:50:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &ip, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Contains checks if provided address is in the white list
|
|
|
|
func (ip *IP) Contains(addr string) (bool, net.IP, error) {
|
2017-10-16 10:46:03 +00:00
|
|
|
if ip.insecure {
|
|
|
|
return true, nil, nil
|
|
|
|
}
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
ipAddr, err := ipFromRemoteAddr(addr)
|
|
|
|
if err != nil {
|
|
|
|
return false, nil, fmt.Errorf("unable to parse address: %s: %s", addr, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
contains, err := ip.ContainsIP(ipAddr)
|
|
|
|
return contains, ipAddr, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// ContainsIP checks if provided address is in the white list
|
|
|
|
func (ip *IP) ContainsIP(addr net.IP) (bool, error) {
|
2017-10-16 10:46:03 +00:00
|
|
|
if ip.insecure {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
|
2017-10-10 12:50:03 +00:00
|
|
|
for _, whiteListIP := range ip.whiteListsIPs {
|
|
|
|
if whiteListIP.Equal(addr) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, whiteListNet := range ip.whiteListsNet {
|
|
|
|
if whiteListNet.Contains(addr) {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ipFromRemoteAddr(addr string) (net.IP, error) {
|
|
|
|
userIP := net.ParseIP(addr)
|
|
|
|
if userIP == nil {
|
|
|
|
return nil, fmt.Errorf("can't parse IP from address %s", addr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return userIP, nil
|
|
|
|
}
|