Password cache map with ttl

This commit is contained in:
Tiago Augusto Pimenta 2018-09-15 16:05:36 -03:00
parent f0c61005dd
commit 134c5508c1
3 changed files with 121 additions and 2 deletions

View file

@ -1,6 +1,6 @@
# Nginx LDAP Auth
Use this in order to provide a ingress authentication over LDAP for Kubernetes, change the ConfigMap inside `k8s.yaml` to match your LDAP server and run:
Use this in order to provide a ingress authentication over LDAP for Kubernetes, change the Secret inside `k8s.yaml` to match your LDAP server and run:
kubectl apply -f k8s.yaml

View file

@ -10,6 +10,7 @@ import (
)
var configFile = flag.String("config", "/etc/nginx-ldap-auth/config.yaml", "Configuration file")
var config Config
func main() {
flag.Parse()
@ -19,7 +20,6 @@ func main() {
log.Fatalf("Could not read file \"%s\": %v\n", *configFile, err)
}
var config Config
err = yaml.Unmarshal(data, &config)
if err != nil {
log.Fatalf("Error on parse config: %v\n", err)

119
src/timeout.go Normal file
View file

@ -0,0 +1,119 @@
package main
import (
"sort"
"sync"
"time"
)
type passtimer struct {
password string
timer *time.Timer
}
type userpass struct {
correct *passtimer
wrong []passtimer
}
var (
passwords map[string]userpass
mutex = sync.RWMutex{}
)
func containsWrongPassword(data *userpass, password string) (int, bool) {
size := len(data.wrong)
if size == 0 {
return 0, false
}
pos := sort.Search(size, func(i int) bool {
return data.wrong[i].password < password
})
return pos, pos < size &&
data.wrong[pos].password == password
}
func getCache(username, password string) (bool, bool) {
defer mutex.RUnlock()
mutex.RLock()
data, found := passwords[username]
if !found {
return false, false
}
if data.correct != nil && (*data.correct).password == password {
return true, true
}
_, found = containsWrongPassword(&data, password)
return false, found
}
func putCache(username, password string, ok bool) {
defer mutex.Unlock()
mutex.Lock()
data, found := passwords[username]
if !found {
data = userpass{}
passwords[username] = data
}
if ok {
if data.correct != nil {
data.correct.timer.Stop()
}
data.correct = &passtimer{
password: password,
timer: time.AfterFunc(config.Timeout.Success, func() {
removeCache(username, "", true)
}),
}
} else {
pass := passtimer{
password: password,
timer: time.AfterFunc(config.Timeout.Wrong, func() {
removeCache(username, password, false)
}),
}
pos, found := containsWrongPassword(&data, password)
if found {
data.wrong[pos].timer.Stop()
} else {
data.wrong = append(data.wrong, passtimer{})
copy(data.wrong[pos+1:], data.wrong[pos:])
}
data.wrong[pos] = pass
}
}
func removeCache(username, password string, ok bool) {
defer mutex.Unlock()
mutex.Lock()
data, found := passwords[username]
if !found {
return
}
if ok {
if data.correct != nil {
data.correct.timer.Stop()
data.correct = nil
}
} else {
pos, found := containsWrongPassword(&data, password)
if found {
data.wrong[pos].timer.Stop()
data.wrong = data.wrong[:pos+copy(data.wrong[pos:], data.wrong[pos+1:])]
}
}
if data.correct == nil && len(data.wrong) == 0 {
delete(passwords, username)
}
}