add various tests for web.go
This commit is contained in:
parent
de9cc37738
commit
8e86f5992e
1 changed files with 374 additions and 0 deletions
374
web_test.go
Normal file
374
web_test.go
Normal 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue