Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ Authentication parameters are passed as URI via `-auth` parameter. Scheme of URI
* `blacklist` - location of file with list of serial numbers of blocked certificates, one per each line in form of hex-encoded colon-separated bytes. Example: `ab:01:02:03`. Empty lines and comments starting with `#` are ignored.
* `reload` - interval for certificate blacklist file reload, if it was modified since last load. Use negative duration to disable autoreload. Default: `15s`.
* `next` - optional URL specifying the next auth provider to chain to, if cert authentication succeeded. Example: `-auth 'cert://?next=static%3A%2F%2F%3Fusername%3Dadmin%26password%3D123456'`.
* `else` - optional URL specifying the next auth provider to chain to, if authentication failed.
* `redis` - use external Redis database to lookup password verifiers for users. The password format is similar to `basicfile` mode or `htpasswd` encoding except username goes into Redis key name, colon is skipped and the rest goes to value of this key. For example, login-password pair `test` / `123456` can be encoded as Redis key `test` with value `$2y$05$zs1EJayCIyYtG.NQVzu9SeNvMP0XYWa42fQv.XNDx33wwbg98SnUq`. Example of auth parameter: `-auth 'redis://?url=redis%3A//default%3A123456Y%40redis-14623.c531.europe-west3-1.gce.redns.redis-cloud.com%3A17954/0&key_prefix=auth_'`. Parameters:
* `url` - URL specifying Redis instance to connect to. See [ParseURL](https://pkg.go.dev/github.com/redis/go-redis/v9#ParseURL) documentation for the complete specification of Redis URL format.
* `key_prefix` - prefix to prepend to each key before lookup. Helps isolate keys under common prefix. Default is empty string (`""`).
Expand Down
25 changes: 21 additions & 4 deletions auth/cert.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type CertAuth struct {
stopOnce sync.Once
stopChan chan struct{}
next Auth
reject Auth
}

func NewCertAuth(param_url *url.URL, logger *clog.CondLogger) (*CertAuth, error) {
Expand Down Expand Up @@ -70,19 +71,32 @@ func NewCertAuth(param_url *url.URL, logger *clog.CondLogger) (*CertAuth, error)
}
auth.next = nap
}
if nextAuth := values.Get("else"); nextAuth != "" {
nap, err := NewAuth(nextAuth, logger)
if err != nil {
return nil, fmt.Errorf("chained auth provider construction failed: %w", err)
}
auth.reject = nap
}

return auth, nil
}

func (auth *CertAuth) handleReject(ctx context.Context, wr http.ResponseWriter, req *http.Request) (string, bool) {
if auth.reject != nil {
return auth.reject.Validate(ctx, wr, req)
}
http.Error(wr, BAD_REQ_MSG, http.StatusBadRequest)
return "", false
}

func (auth *CertAuth) Validate(ctx context.Context, wr http.ResponseWriter, req *http.Request) (string, bool) {
if req.TLS == nil || len(req.TLS.VerifiedChains) < 1 || len(req.TLS.VerifiedChains[0]) < 1 {
http.Error(wr, BAD_REQ_MSG, http.StatusBadRequest)
return "", false
return auth.handleReject(ctx, wr, req)
}
eeCert := req.TLS.VerifiedChains[0][0]
if auth.blacklist.Load().file.Has(eeCert.SerialNumber) {
http.Error(wr, BAD_REQ_MSG, http.StatusBadRequest)
return "", false
return auth.handleReject(ctx, wr, req)
}
if auth.next != nil {
return auth.next.Validate(ctx, wr, req)
Expand All @@ -99,6 +113,9 @@ func (auth *CertAuth) Stop() {
if auth.next != nil {
auth.next.Stop()
}
if auth.reject != nil {
auth.reject.Stop()
}
close(auth.stopChan)
})
}
Expand Down
Loading