add various tests for web.go

This commit is contained in:
Thomas Preisner 2021-09-12 01:19:51 +02:00
parent de9cc37738
commit 8e86f5992e

374
web_test.go Normal file
View file

@ -0,0 +1,374 @@
package main
import (
"log"
"net"
"net/http"
"reflect"
"testing"
"github.com/google/go-cmp/cmp"
)
var (
addr = "localhost"
port uint16 = 1234
rawCfg = Config{
ServerPort: port,
Users: []User{
User{
Username: "user",
// "secret" -> bcrypt-hashed
Password: "$2a$12$He9X4KNAFJQy0CL2c9.Df.tjXwCkideOogwJ7DNtO/I8qzeJZfc3i",
Records: []string{
"record.example.org",
},
},
User{
Username: "user2",
// "secret" -> bcrypt-hashed
Password: "$2a$12$He9X4KNAFJQy0CL2c9.Df.tjXwCkideOogwJ7DNtO/I8qzeJZfc3i",
Records: []string{
"record2.example.org",
},
},
User{
Username: "bad-hash",
Password: "secret",
Records: []string{
"record3.example.org",
},
},
},
RRConfigs: []RRConfig{
RRConfig{
Recordname: "record.example.org",
Zonename: "zone.example.org",
Nameserver: "ns1.example.org",
Tsigalgo: "hmac-sha256",
Tsigid: "tsig-id",
Tsigkey: "some-secret-key",
},
RRConfig{
Recordname: "record2.example.org",
Zonename: "zone.example.org",
Nameserver: "ns1.example.org",
Tsigalgo: "hmac-sha256",
Tsigid: "tsig-id",
Tsigkey: "some-secret-key",
},
RRConfig{
Recordname: "record3.example.org",
Zonename: "zone.example.org",
Nameserver: "ns1.example.org",
Tsigalgo: "hmac-sha256",
Tsigid: "tsig-id",
Tsigkey: "some-secret-key",
},
},
}
cfg *Config
)
// pre-initialize config for all testcases
func init() {
var err error
cfg, err = prepareConfig(&rawCfg)
if err != nil {
log.Fatalf("Preparing config failed: %v", err)
}
}
func prepareRequest(t *testing.T, params map[string]string, headers map[string]string) *http.Request {
req, err := http.NewRequest("GET", "http://"+addr, nil)
if err != nil {
t.Fatalf("Generating request failed: %v", err)
}
// append http parameters to http request
q := req.URL.Query()
for k, v := range params {
q.Add(k, v)
}
req.URL.RawQuery = q.Encode()
// set headers
for k, v := range headers {
req.Header.Set(k, v)
}
return req
}
type credentials struct {
username string
password string
}
func TestIsAuthenticated(t *testing.T) {
tests := []struct {
name string
auth *credentials
expUser *User
}{
{
"missing basicauth",
nil,
nil,
},
{
"non-existent user",
&credentials{
"unknown",
"secret",
},
nil,
},
{
"invalid hash",
&credentials{
"bad-hash",
"secret",
},
nil,
},
{
"correct user",
&credentials{
"user",
"secret",
},
&User{
Username: "user",
Password: "$2a$12$He9X4KNAFJQy0CL2c9.Df.tjXwCkideOogwJ7DNtO/I8qzeJZfc3i",
Records: []string{
"record.example.org",
},
records: map[string]bool{
"record.example.org": true,
},
},
},
}
for _, tc := range tests {
req := prepareRequest(t, nil, nil)
if tc.auth != nil {
req.SetBasicAuth(tc.auth.username, tc.auth.password)
}
res := isAuthenticated(cfg, req)
if !reflect.DeepEqual(tc.expUser, res) {
t.Errorf("%s: res: %s", tc.name,
cmp.Diff(tc.expUser, res, cmp.AllowUnexported(User{})))
}
}
}
func TestVerifyHostname(t *testing.T) {
tests := []struct {
name string
user *User
hostname string
expMsg string
expRrconfig *RRConfig
}{
{
"empty hostname",
cfg.users["user"],
"",
"nohost",
nil,
},
{
"user not allowed",
cfg.users["user2"],
"record.example.org",
"badauth",
nil,
},
{
"correct hostname",
cfg.users["user"],
"record.example.org",
"",
cfg.rrconfigs["record.example.org"],
},
}
for _, tc := range tests {
msg, rrconfig := verifyHostname(cfg, tc.user, tc.hostname)
if !reflect.DeepEqual(tc.expMsg, msg) {
t.Errorf("%s: res: %s", tc.name,
cmp.Diff(tc.expMsg, msg))
}
if !reflect.DeepEqual(tc.expRrconfig, rrconfig) {
t.Errorf("%s: res: %s", tc.name,
cmp.Diff(tc.expRrconfig, rrconfig))
}
}
}
func TestGetIpAddress(t *testing.T) {
tests := []struct {
name string
params map[string]string
headers map[string]string
remoteAddr string
expAddr net.IP
}{
{
"no address",
nil,
nil,
"",
nil,
},
{
"remote addr - invalid ip",
nil,
nil,
"1.1.1:1234",
nil,
},
{
"remote addr - missing port",
nil,
nil,
"1.1.1.1",
nil,
},
{
"remote addr - valid",
nil,
nil,
"1.1.1.1:1234",
net.ParseIP("1.1.1.1"),
},
{
"X-Real-IP - empty",
nil,
map[string]string{
"X-Real-IP": "",
},
"1.1.1.1:1234",
net.ParseIP("1.1.1.1"),
},
{
"X-Real-IP - invalid",
nil,
map[string]string{
"X-Real-IP": "2.2.2",
},
"1.1.1.1:1234",
nil,
},
{
"X-Real-IP - valid",
nil,
map[string]string{
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
net.ParseIP("2.2.2.2"),
},
{
"X-Forwarded-For - empty",
nil,
map[string]string{
"X-Forwarded-For": "",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
net.ParseIP("2.2.2.2"),
},
{
"X-Forwarded-For - comma only",
nil,
map[string]string{
"X-Forwarded-For": ",",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
nil,
},
{
"X-Forwarded-For - invalid entry",
nil,
map[string]string{
"X-Forwarded-For": "3.3.3",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
nil,
},
{
"X-Forwarded-For - one entry",
nil,
map[string]string{
"X-Forwarded-For": "3.3.3.3",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
net.ParseIP("3.3.3.3"),
},
{
"X-Forwarded-For - multiple entries",
nil,
map[string]string{
"X-Forwarded-For": "3.3.3.3, 3.3.3.4",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
net.ParseIP("3.3.3.3"),
},
{
"myip - empty",
map[string]string{
"myip": "",
},
map[string]string{
"X-Forwarded-For": "3.3.3.3, 3.3.3.4",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
net.ParseIP("3.3.3.3"),
},
{
"myip - invalid",
map[string]string{
"myip": "1.2.3",
},
map[string]string{
"X-Forwarded-For": "3.3.3.3, 3.3.3.4",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
nil,
},
{
"myip - valid",
map[string]string{
"myip": "4.4.4.4",
},
map[string]string{
"X-Forwarded-For": "3.3.3.3, 3.3.3.4",
"X-Real-IP": "2.2.2.2",
},
"1.1.1.1:1234",
net.ParseIP("4.4.4.4"),
},
}
for _, tc := range tests {
req := prepareRequest(t, tc.params, tc.headers)
req.RemoteAddr = tc.remoteAddr
addr := getIpAddress(req)
if !reflect.DeepEqual(tc.expAddr, addr) {
t.Errorf("%s: res: %s", tc.name,
cmp.Diff(tc.expAddr, addr))
}
}
}