fix(auth): redisLoader copy-paste bug, httpLoader.Close leak, reload data wipe, silent parse errors
- redisLoader branch used fileLoader instead of redisLoader (copy-paste bug) - Close() was missing httpLoader.Close() (resource leak vs admission pattern) - reload() now preserves kvs on load() error instead of wiping to static-only - load() propagates first loader error, reload() returns early on load failure - parseAuths scanner errors now logged instead of silently discarded - http plugin drains body on non-200 to allow keep-alive connection reuse - Replace manual map-copy loops with maps.Copy
This commit is contained in:
+36
-21
@@ -4,6 +4,7 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
|
"maps"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -138,16 +139,15 @@ func (p *authenticator) periodReload(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *authenticator) reload(ctx context.Context) (err error) {
|
func (p *authenticator) reload(ctx context.Context) error {
|
||||||
kvs := make(map[string]string)
|
kvs := make(map[string]string)
|
||||||
for k, v := range p.options.auths {
|
maps.Copy(kvs, p.options.auths)
|
||||||
kvs[k] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
m, err := p.load(ctx)
|
m, err := p.load(ctx)
|
||||||
for k, v := range m {
|
if err != nil {
|
||||||
kvs[k] = v
|
return err
|
||||||
}
|
}
|
||||||
|
maps.Copy(kvs, m)
|
||||||
|
|
||||||
p.logger.Debugf("load items %d", len(m))
|
p.logger.Debugf("load items %d", len(m))
|
||||||
|
|
||||||
@@ -156,47 +156,56 @@ func (p *authenticator) reload(ctx context.Context) (err error) {
|
|||||||
|
|
||||||
p.kvs = kvs
|
p.kvs = kvs
|
||||||
|
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *authenticator) load(ctx context.Context) (m map[string]string, err error) {
|
func (p *authenticator) load(ctx context.Context) (map[string]string, error) {
|
||||||
m = make(map[string]string)
|
m := make(map[string]string)
|
||||||
|
var loadErr error
|
||||||
|
|
||||||
if p.options.fileLoader != nil {
|
if p.options.fileLoader != nil {
|
||||||
if mapper, ok := p.options.fileLoader.(loader.Mapper); ok {
|
if mapper, ok := p.options.fileLoader.(loader.Mapper); ok {
|
||||||
auths, er := mapper.Map(ctx)
|
auths, er := mapper.Map(ctx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
p.logger.Warnf("file loader: %v", er)
|
p.logger.Warnf("file loader: %v", er)
|
||||||
|
loadErr = er
|
||||||
}
|
}
|
||||||
m = auths
|
m = auths
|
||||||
} else {
|
} else {
|
||||||
r, er := p.options.fileLoader.Load(ctx)
|
r, er := p.options.fileLoader.Load(ctx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
p.logger.Warnf("file loader: %v", er)
|
p.logger.Warnf("file loader: %v", er)
|
||||||
|
loadErr = er
|
||||||
}
|
}
|
||||||
if auths, _ := p.parseAuths(r); auths != nil {
|
if auths, err := p.parseAuths(r); err == nil {
|
||||||
m = auths
|
m = auths
|
||||||
|
} else {
|
||||||
|
p.logger.Warnf("file loader parse: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.options.redisLoader != nil {
|
if p.options.redisLoader != nil {
|
||||||
if mapper, ok := p.options.fileLoader.(loader.Mapper); ok {
|
if mapper, ok := p.options.redisLoader.(loader.Mapper); ok {
|
||||||
auths, er := mapper.Map(ctx)
|
auths, er := mapper.Map(ctx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
p.logger.Warnf("file loader: %v", er)
|
p.logger.Warnf("redis loader: %v", er)
|
||||||
|
if loadErr == nil {
|
||||||
|
loadErr = er
|
||||||
}
|
}
|
||||||
for k, v := range auths {
|
|
||||||
m[k] = v
|
|
||||||
}
|
}
|
||||||
|
maps.Copy(m, auths)
|
||||||
} else {
|
} else {
|
||||||
r, er := p.options.redisLoader.Load(ctx)
|
r, er := p.options.redisLoader.Load(ctx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
p.logger.Warnf("redis loader: %v", er)
|
p.logger.Warnf("redis loader: %v", er)
|
||||||
|
if loadErr == nil {
|
||||||
|
loadErr = er
|
||||||
}
|
}
|
||||||
if auths, _ := p.parseAuths(r); auths != nil {
|
|
||||||
for k, v := range auths {
|
|
||||||
m[k] = v
|
|
||||||
}
|
}
|
||||||
|
if auths, err := p.parseAuths(r); err == nil {
|
||||||
|
maps.Copy(m, auths)
|
||||||
|
} else {
|
||||||
|
p.logger.Warnf("redis loader parse: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,15 +213,18 @@ func (p *authenticator) load(ctx context.Context) (m map[string]string, err erro
|
|||||||
r, er := p.options.httpLoader.Load(ctx)
|
r, er := p.options.httpLoader.Load(ctx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
p.logger.Warnf("http loader: %v", er)
|
p.logger.Warnf("http loader: %v", er)
|
||||||
|
if loadErr == nil {
|
||||||
|
loadErr = er
|
||||||
}
|
}
|
||||||
if auths, _ := p.parseAuths(r); auths != nil {
|
|
||||||
for k, v := range auths {
|
|
||||||
m[k] = v
|
|
||||||
}
|
}
|
||||||
|
if auths, err := p.parseAuths(r); err == nil {
|
||||||
|
maps.Copy(m, auths)
|
||||||
|
} else {
|
||||||
|
p.logger.Warnf("http loader parse: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return m, loadErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *authenticator) parseAuths(r io.Reader) (auths map[string]string, err error) {
|
func (p *authenticator) parseAuths(r io.Reader) (auths map[string]string, err error) {
|
||||||
@@ -254,6 +266,9 @@ func (p *authenticator) Close() error {
|
|||||||
if p.options.redisLoader != nil {
|
if p.options.redisLoader != nil {
|
||||||
p.options.redisLoader.Close()
|
p.options.redisLoader.Close()
|
||||||
}
|
}
|
||||||
|
if p.options.httpLoader != nil {
|
||||||
|
p.options.httpLoader.Close()
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-gost/core/auth"
|
"github.com/go-gost/core/auth"
|
||||||
@@ -91,6 +92,7 @@ func (p *httpPlugin) Authenticate(ctx context.Context, user, password string, op
|
|||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
io.Copy(io.Discard, resp.Body)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user