Skip to content

Commit

Permalink
Fix registration issues, add validation in settings, improve dhcp to …
Browse files Browse the repository at this point in the history
…avoid deadlock when subnet is exhausted
  • Loading branch information
NHAS committed May 13, 2024
1 parent 1566c26 commit 724cbc3
Show file tree
Hide file tree
Showing 9 changed files with 141 additions and 54 deletions.
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ require (
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/fxamacker/cbor/v2 v2.5.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-webauthn/x v0.1.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
Expand All @@ -54,6 +58,7 @@ require (
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
github.com/mdlayher/genetlink v1.3.2 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBF
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
github.com/fxamacker/cbor/v2 v2.5.0 h1:oHsG0V/Q6E/wqTS2O1Cozzsy69nqCiguo5Q1a1ADivE=
github.com/fxamacker/cbor/v2 v2.5.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
Expand All @@ -71,6 +73,12 @@ github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
Expand Down Expand Up @@ -160,6 +168,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
Expand Down
72 changes: 57 additions & 15 deletions internal/data/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strings"

"github.com/NHAS/wag/internal/data/validators"
"github.com/go-playground/validator/v10"
clientv3 "go.etcd.io/etcd/client/v3"
)

Expand Down Expand Up @@ -342,21 +343,34 @@ type AllSettings struct {
}

type LoginSettings struct {
SessionInactivityTimeoutMinutes int
MaxSessionLifetimeMinutes int
Lockout int
SessionInactivityTimeoutMinutes int `validate:"required,number"`
MaxSessionLifetimeMinutes int `validate:"required,number"`
Lockout int `validate:"required,number"`

DefaultMFAMethod string
EnabledMFAMethods []string
DefaultMFAMethod string `validate:"required"`
EnabledMFAMethods []string `validate:"required,lt=10,dive,required"`

Domain string
Issuer string
Domain string `validate:"required"`
Issuer string `validate:"required"`

OidcDetails OIDC
PamDetails PAM
}

func (lg *LoginSettings) ToWriteOps() (ret []clientv3.Op) {
func (lg *LoginSettings) Validate() error {
lg.Domain = strings.TrimSpace(lg.Domain)
lg.Issuer = strings.TrimSpace(lg.Issuer)

validate := validator.New(validator.WithRequiredStructEnabled())

return validate.Struct(lg)
}

func (lg *LoginSettings) ToWriteOps() (ret []clientv3.Op, err error) {

if err := lg.Validate(); err != nil {
return nil, err
}

b, _ := json.Marshal(lg.SessionInactivityTimeoutMinutes)
ret = append(ret, clientv3.OpPut(InactivityTimeoutKey, string(b)))
Expand Down Expand Up @@ -389,15 +403,33 @@ func (lg *LoginSettings) ToWriteOps() (ret []clientv3.Op) {
}

type GeneralSettings struct {
HelpMail string
ExternalAddress string
DNS []string
HelpMail string `validate:"required,email"`
ExternalAddress string `validate:"required,hostname|hostname_port|ip"`
DNS []string `validate:"omitempty,dive,ip"`

WireguardConfigFilename string
WireguardConfigFilename string `validate:"required"`
CheckUpdates bool
}

func (gs *GeneralSettings) ToWriteOps() (ret []clientv3.Op) {
func (gs *GeneralSettings) Validate() error {

gs.HelpMail = strings.TrimSpace(gs.HelpMail)
gs.ExternalAddress = strings.TrimSpace(gs.ExternalAddress)
gs.WireguardConfigFilename = strings.TrimSpace(gs.WireguardConfigFilename)
for i := range gs.DNS {
gs.DNS[i] = strings.TrimSpace(gs.DNS[i])
}

validate := validator.New(validator.WithRequiredStructEnabled())

return validate.Struct(gs)
}

func (gs *GeneralSettings) ToWriteOps() (ret []clientv3.Op, err error) {

if err := gs.Validate(); err != nil {
return nil, err
}

b, _ := json.Marshal(gs.HelpMail)
ret = append(ret, clientv3.OpPut(helpMailKey, string(b)))
Expand Down Expand Up @@ -541,14 +573,24 @@ func GetAllSettings() (s AllSettings, err error) {
}

func SetLoginSettings(loginSettings LoginSettings) error {

writeOps, err := loginSettings.ToWriteOps()
if err != nil {
return err
}

txn := etcd.Txn(context.Background())
_, err := txn.Then(loginSettings.ToWriteOps()...).Commit()
_, err = txn.Then(writeOps...).Commit()
return err
}

func SetGeneralSettings(generalSettings GeneralSettings) error {
txn := etcd.Txn(context.Background())
_, err := txn.Then(generalSettings.ToWriteOps()...).Commit()
writeOPs, err := generalSettings.ToWriteOps()
if err != nil {
return err
}
_, err = txn.Then(writeOPs...).Commit()
return err
}

Expand Down
2 changes: 1 addition & 1 deletion internal/data/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ func AddDevice(username, publickey string) (Device, error) {
return Device{}, err
}

address, err := getNextIP(config.Values.Wireguard.Range.String())
address, err := getNextIP(config.Values.Wireguard.Address)
if err != nil {
return Device{}, err
}
Expand Down
41 changes: 31 additions & 10 deletions internal/data/dhcp.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,39 @@ func getNextIP(subnet string) (string, error) {
}

used, _ := cidr.Mask.Size()
addresses := int(math.Pow(2, float64(32-used))) - 2 // Do not allocate largest address or 0
if addresses < 1 {
return "", errors.New("no addresses available")
maxNumberOfAddresses := int(math.Pow(2, float64(32-used))) - 2 // Do not allocate largest address or 0
if maxNumberOfAddresses < 1 {
return "", errors.New("subnet is too small to contain a new device")
}

// Choose a random number that cannot be 0
addressAttempt := rand.Intn(addresses) + 1
addressAttempt := rand.Intn(maxNumberOfAddresses) + 1
addr := incrementIP(cidr.IP, uint(addressAttempt))

if serverIP.Equal(addr) {
addr = incrementIP(addr, 1)
}

lease, err := clientv3.NewLease(etcd).Grant(context.Background(), 3)
if err != nil {
return "", err
}

if serverIP.Equal(addr) {
addr = incrementIP(addr, 1)
}

startIP := addr
for {

if serverIP.Equal(addr) {
addr = incrementIP(addr, 1)
}

txn := etcd.Txn(context.Background())
txn.If(clientv3util.KeyMissing("deviceref-"+addr.String()), clientv3util.KeyMissing("ip-hold-"+addr.String()))
txn.Then(clientv3.OpPut("ip-hold-"+addr.String(), addr.String(), clientv3.WithLease(lease.ID)))
txn.If(
clientv3util.KeyMissing("deviceref-"+addr.String()),
clientv3util.KeyMissing("ip-hold-"+addr.String()),
)
txn.Then(
clientv3.OpPut("ip-hold-"+addr.String(), addr.String(), clientv3.WithLease(lease.ID)),
)

resp, err := txn.Commit()
if err != nil {
Expand All @@ -64,6 +75,16 @@ func getNextIP(subnet string) (string, error) {
}

addr = incrementIP(addr, 1)
if cidr.Contains(addr) {
continue
} else {
addr = incrementIP(cidr.IP, 1)
}

if addr.Equal(startIP) {
return "", errors.New("unable to obtain ip lease, subnet is full")
}

}

}
3 changes: 3 additions & 0 deletions internal/data/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"errors"
"strings"

"github.com/NHAS/wag/internal/webserver/authenticators/types"
clientv3 "go.etcd.io/etcd/client/v3"
"go.etcd.io/etcd/client/v3/clientv3util"
)
Expand Down Expand Up @@ -323,6 +324,8 @@ func CreateUserDataAccount(username string) (UserModel, error) {

newUser := UserModel{
Username: username,
Mfa: string(types.Unset),
MfaType: string(types.Unset),
}
b, _ := json.Marshal(&newUser)

Expand Down
Loading

0 comments on commit 724cbc3

Please sign in to comment.