mirror of
https://github.com/TecharoHQ/anubis.git
synced 2026-05-09 00:22:53 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd6b44df90 |
@@ -31,7 +31,7 @@ jobs:
|
|||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ jobs:
|
|||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- name: Check go.mod and go.sum in main directory
|
- name: Check go.mod and go.sum in main directory
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ jobs:
|
|||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- name: Cache playwright binaries
|
- name: Cache playwright binaries
|
||||||
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
|
||||||
@@ -61,4 +61,4 @@ jobs:
|
|||||||
|
|
||||||
- name: Govulncheck
|
- name: Govulncheck
|
||||||
run: |
|
run: |
|
||||||
go tool govulncheck ./... ||:
|
go tool govulncheck ./...
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- name: install node deps
|
- name: install node deps
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ jobs:
|
|||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- name: install node deps
|
- name: install node deps
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ jobs:
|
|||||||
node-version: "24.11.0"
|
node-version: "24.11.0"
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
- uses: ko-build/setup-ko@d006021bd0c28d1ce33a07e7943d48b079944c8d # v0.9
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ jobs:
|
|||||||
|
|
||||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0
|
||||||
with:
|
with:
|
||||||
go-version: "stable"
|
go-version: "1.25.4"
|
||||||
|
|
||||||
- name: Run CI
|
- name: Run CI
|
||||||
run: go run ./utils/cmd/backoff-retry bash test/ssh-ci/rigging.sh ${{ matrix.host }}
|
run: go run ./utils/cmd/backoff-retry bash test/ssh-ci/rigging.sh ${{ matrix.host }}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ build: assets
|
|||||||
lint: assets
|
lint: assets
|
||||||
$(GO) vet ./...
|
$(GO) vet ./...
|
||||||
$(GO) tool staticcheck ./...
|
$(GO) tool staticcheck ./...
|
||||||
|
$(GO) tool govulncheck ./...
|
||||||
|
|
||||||
prebaked-build:
|
prebaked-build:
|
||||||
$(GO) build -o ./var/anubis -ldflags "-X 'github.com/TecharoHQ/anubis.Version=$(VERSION)'" ./cmd/anubis
|
$(GO) build -o ./var/anubis -ldflags "-X 'github.com/TecharoHQ/anubis.Version=$(VERSION)'" ./cmd/anubis
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
- Fixed mixed tab/space indentation in Caddy documentation code block
|
- fix: prevent nil pointer panic in challenge validation when threshold rules match during PassChallenge (#1463)
|
||||||
|
|
||||||
<!-- This changes the project to: -->
|
<!-- This changes the project to: -->
|
||||||
|
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ yourdomain.example.com {
|
|||||||
tls your@email.address
|
tls your@email.address
|
||||||
|
|
||||||
reverse_proxy http://anubis:3000 {
|
reverse_proxy http://anubis:3000 {
|
||||||
header_up X-Real-Ip {remote_host}
|
header_up X-Real-Ip {remote_host}
|
||||||
header_up X-Http-Version {http.request.proto}
|
header_up X-Http-Version {http.request.proto}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -393,32 +393,6 @@ logging:
|
|||||||
|
|
||||||
When files are rotated out, the old files will be named after the rotation timestamp in [RFC 3339 format](https://www.rfc-editor.org/rfc/rfc3339).
|
When files are rotated out, the old files will be named after the rotation timestamp in [RFC 3339 format](https://www.rfc-editor.org/rfc/rfc3339).
|
||||||
|
|
||||||
:::note
|
|
||||||
|
|
||||||
If you are running Anubis in systemd via a native package, the default systemd unit settings are very restrictive and will forbid writing to folders in `/var/log`. In order to fix this, please make a [drop-in unit](https://www.flatcar.org/docs/latest/setup/systemd/drop-in-units/) like the following:
|
|
||||||
|
|
||||||
```text
|
|
||||||
# /etc/systemd/anubis@instance-name.service.d/50-var-log-readwrite.conf
|
|
||||||
[Service]
|
|
||||||
ReadWritePaths=/run /var/log/anubis
|
|
||||||
```
|
|
||||||
|
|
||||||
Once you write this to the correct place, reload the systemd configuration:
|
|
||||||
|
|
||||||
```text
|
|
||||||
sudo systemctl daemon-reload
|
|
||||||
```
|
|
||||||
|
|
||||||
And then restart Anubis:
|
|
||||||
|
|
||||||
```text
|
|
||||||
sudo systemctl restart anubis@instance-name
|
|
||||||
```
|
|
||||||
|
|
||||||
You may be required to make drop-ins for each Anubis instance depending on the facts and circumstances of your deployment.
|
|
||||||
|
|
||||||
:::
|
|
||||||
|
|
||||||
### `stdio` sink
|
### `stdio` sink
|
||||||
|
|
||||||
By default, Anubis logs everything to the standard error stream of its process. This requires no configuration:
|
By default, Anubis logs everything to the standard error stream of its process. This requires no configuration:
|
||||||
|
|||||||
+21
-2
@@ -106,6 +106,13 @@ func (s *Server) issueChallenge(ctx context.Context, r *http.Request, lg *slog.L
|
|||||||
//return nil, errors.New("[unexpected] this codepath should be impossible, asked to issue a challenge for a non-challenge rule")
|
//return nil, errors.New("[unexpected] this codepath should be impossible, asked to issue a challenge for a non-challenge rule")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rule.Challenge == nil {
|
||||||
|
rule.Challenge = &config.ChallengeRules{
|
||||||
|
Difficulty: s.policy.DefaultDifficulty,
|
||||||
|
Algorithm: config.DefaultAlgorithm,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
id, err := uuid.NewV7()
|
id, err := uuid.NewV7()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -491,7 +498,11 @@ func (s *Server) PassChallenge(w http.ResponseWriter, r *http.Request) {
|
|||||||
chall, err := s.getChallenge(r)
|
chall, err := s.getChallenge(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Error("getChallenge failed", "err", err)
|
lg.Error("getChallenge failed", "err", err)
|
||||||
s.respondWithError(w, r, fmt.Sprintf("%s: %s", localizer.T("internal_server_error"), rule.Challenge.Algorithm), makeCode(err))
|
algorithm := "unknown"
|
||||||
|
if rule.Challenge != nil {
|
||||||
|
algorithm = rule.Challenge.Algorithm
|
||||||
|
}
|
||||||
|
s.respondWithError(w, r, fmt.Sprintf("%s: %s", localizer.T("internal_server_error"), algorithm), makeCode(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,8 +649,16 @@ func (s *Server) check(r *http.Request, lg *slog.Logger) (policy.CheckResult, *p
|
|||||||
}
|
}
|
||||||
|
|
||||||
if matches {
|
if matches {
|
||||||
|
challRules := t.Challenge
|
||||||
|
if challRules == nil {
|
||||||
|
// Non-CHALLENGE thresholds (ALLOW/DENY) don't have challenge config.
|
||||||
|
// Use an empty struct so hydrateChallengeRule can fill from stored
|
||||||
|
// challenge data during validation, rather than baking in defaults
|
||||||
|
// that could mismatch the difficulty the client actually solved for.
|
||||||
|
challRules = &config.ChallengeRules{}
|
||||||
|
}
|
||||||
return cr("threshold/"+t.Name, t.Action, weight), &policy.Bot{
|
return cr("threshold/"+t.Name, t.Action, weight), &policy.Bot{
|
||||||
Challenge: t.Challenge,
|
Challenge: challRules,
|
||||||
Rules: &checker.List{},
|
Rules: &checker.List{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ var (
|
|||||||
ErrFailed = errors.New("challenge: user failed challenge")
|
ErrFailed = errors.New("challenge: user failed challenge")
|
||||||
ErrMissingField = errors.New("challenge: missing field")
|
ErrMissingField = errors.New("challenge: missing field")
|
||||||
ErrInvalidFormat = errors.New("challenge: field has invalid format")
|
ErrInvalidFormat = errors.New("challenge: field has invalid format")
|
||||||
|
ErrInvalidInput = errors.New("challenge: input is nil or missing required fields")
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewError(verb, publicReason string, privateReason error) *Error {
|
func NewError(verb, publicReason string, privateReason error) *Error {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package challenge
|
package challenge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -50,12 +51,44 @@ type IssueInput struct {
|
|||||||
Store store.Interface
|
Store store.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (in *IssueInput) Valid() error {
|
||||||
|
if in == nil {
|
||||||
|
return fmt.Errorf("%w: IssueInput is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
if in.Rule == nil {
|
||||||
|
return fmt.Errorf("%w: Rule is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
if in.Rule.Challenge == nil {
|
||||||
|
return fmt.Errorf("%w: Rule.Challenge is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
if in.Challenge == nil {
|
||||||
|
return fmt.Errorf("%w: Challenge is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type ValidateInput struct {
|
type ValidateInput struct {
|
||||||
Rule *policy.Bot
|
Rule *policy.Bot
|
||||||
Challenge *Challenge
|
Challenge *Challenge
|
||||||
Store store.Interface
|
Store store.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (in *ValidateInput) Valid() error {
|
||||||
|
if in == nil {
|
||||||
|
return fmt.Errorf("%w: ValidateInput is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
if in.Rule == nil {
|
||||||
|
return fmt.Errorf("%w: Rule is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
if in.Rule.Challenge == nil {
|
||||||
|
return fmt.Errorf("%w: Rule.Challenge is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
if in.Challenge == nil {
|
||||||
|
return fmt.Errorf("%w: Challenge is nil", ErrInvalidInput)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Impl interface {
|
type Impl interface {
|
||||||
// Setup registers any additional routes with the Impl for assets or API routes.
|
// Setup registers any additional routes with the Impl for assets or API routes.
|
||||||
Setup(mux *http.ServeMux)
|
Setup(mux *http.ServeMux)
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ type Impl struct{}
|
|||||||
func (i *Impl) Setup(mux *http.ServeMux) {}
|
func (i *Impl) Setup(mux *http.ServeMux) {}
|
||||||
|
|
||||||
func (i *Impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in *challenge.IssueInput) (templ.Component, error) {
|
func (i *Impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in *challenge.IssueInput) (templ.Component, error) {
|
||||||
|
if err := in.Valid(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
u, err := r.URL.Parse(anubis.BasePrefix + "/.within.website/x/cmd/anubis/api/pass-challenge")
|
u, err := r.URL.Parse(anubis.BasePrefix + "/.within.website/x/cmd/anubis/api/pass-challenge")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't render page: %w", err)
|
return nil, fmt.Errorf("can't render page: %w", err)
|
||||||
@@ -49,6 +53,10 @@ func (i *Impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *challenge.ValidateInput) error {
|
func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *challenge.ValidateInput) error {
|
||||||
|
if err := in.Valid(); err != nil {
|
||||||
|
return challenge.NewError("validate", "invalid input", err)
|
||||||
|
}
|
||||||
|
|
||||||
wantTime := in.Challenge.IssuedAt.Add(time.Duration(in.Rule.Challenge.Difficulty) * 800 * time.Millisecond)
|
wantTime := in.Challenge.IssuedAt.Add(time.Duration(in.Rule.Challenge.Difficulty) * 800 * time.Millisecond)
|
||||||
|
|
||||||
if time.Now().Before(wantTime) {
|
if time.Now().Before(wantTime) {
|
||||||
|
|||||||
@@ -39,6 +39,10 @@ type impl struct{}
|
|||||||
func (i *impl) Setup(mux *http.ServeMux) {}
|
func (i *impl) Setup(mux *http.ServeMux) {}
|
||||||
|
|
||||||
func (i *impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in *challenge.IssueInput) (templ.Component, error) {
|
func (i *impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in *challenge.IssueInput) (templ.Component, error) {
|
||||||
|
if err := in.Valid(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
u, err := r.URL.Parse(anubis.BasePrefix + "/.within.website/x/cmd/anubis/api/pass-challenge")
|
u, err := r.URL.Parse(anubis.BasePrefix + "/.within.website/x/cmd/anubis/api/pass-challenge")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't render page: %w", err)
|
return nil, fmt.Errorf("can't render page: %w", err)
|
||||||
@@ -57,6 +61,10 @@ func (i *impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *impl) Validate(r *http.Request, lg *slog.Logger, in *challenge.ValidateInput) error {
|
func (i *impl) Validate(r *http.Request, lg *slog.Logger, in *challenge.ValidateInput) error {
|
||||||
|
if err := in.Valid(); err != nil {
|
||||||
|
return challenge.NewError("validate", "invalid input", err)
|
||||||
|
}
|
||||||
|
|
||||||
wantTime := in.Challenge.IssuedAt.Add(time.Duration(in.Rule.Challenge.Difficulty) * 80 * time.Millisecond)
|
wantTime := in.Challenge.IssuedAt.Add(time.Duration(in.Rule.Challenge.Difficulty) * 80 * time.Millisecond)
|
||||||
|
|
||||||
if time.Now().Before(wantTime) {
|
if time.Now().Before(wantTime) {
|
||||||
|
|||||||
@@ -33,6 +33,10 @@ func (i *Impl) Issue(w http.ResponseWriter, r *http.Request, lg *slog.Logger, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *chall.ValidateInput) error {
|
func (i *Impl) Validate(r *http.Request, lg *slog.Logger, in *chall.ValidateInput) error {
|
||||||
|
if err := in.Valid(); err != nil {
|
||||||
|
return chall.NewError("validate", "invalid input", err)
|
||||||
|
}
|
||||||
|
|
||||||
rule := in.Rule
|
rule := in.Rule
|
||||||
challenge := in.Challenge.RandomData
|
challenge := in.Challenge.RandomData
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,62 @@ func mkRequest(t *testing.T, values map[string]string) *http.Request {
|
|||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestValidateNilRuleChallenge reproduces the panic from
|
||||||
|
// https://github.com/TecharoHQ/anubis/issues/1463
|
||||||
|
//
|
||||||
|
// When a threshold rule matches during PassChallenge, check() can return
|
||||||
|
// a policy.Bot with Challenge == nil. After hydrateChallengeRule fails to
|
||||||
|
// run (or the error path hits before it), Validate dereferences
|
||||||
|
// rule.Challenge.Difficulty and panics.
|
||||||
|
func TestValidateNilRuleChallenge(t *testing.T) {
|
||||||
|
i := &Impl{Algorithm: "fast"}
|
||||||
|
lg := slog.With()
|
||||||
|
|
||||||
|
// This is the exact response for SHA256("hunter" + "0") with 0 leading zeros required.
|
||||||
|
const challengeStr = "hunter"
|
||||||
|
const response = "2652bdba8fb4d2ab39ef28d8534d7694c557a4ae146c1e9237bd8d950280500e"
|
||||||
|
|
||||||
|
req := mkRequest(t, map[string]string{
|
||||||
|
"nonce": "0",
|
||||||
|
"elapsedTime": "69",
|
||||||
|
"response": response,
|
||||||
|
})
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
name string
|
||||||
|
input *challenge.ValidateInput
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "nil-rule-challenge",
|
||||||
|
input: &challenge.ValidateInput{
|
||||||
|
Rule: &policy.Bot{},
|
||||||
|
Challenge: &challenge.Challenge{RandomData: challengeStr},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil-rule",
|
||||||
|
input: &challenge.ValidateInput{
|
||||||
|
Challenge: &challenge.Challenge{RandomData: challengeStr},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil-challenge",
|
||||||
|
input: &challenge.ValidateInput{Rule: &policy.Bot{Challenge: &config.ChallengeRules{Algorithm: "fast"}}},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil-input",
|
||||||
|
input: nil,
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := i.Validate(req, lg, tc.input)
|
||||||
|
if !errors.Is(err, challenge.ErrInvalidInput) {
|
||||||
|
t.Fatalf("expected ErrInvalidInput, got: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBasic(t *testing.T) {
|
func TestBasic(t *testing.T) {
|
||||||
i := &Impl{Algorithm: "fast"}
|
i := &Impl{Algorithm: "fast"}
|
||||||
bot := &policy.Bot{
|
bot := &policy.Bot{
|
||||||
|
|||||||
+11
-3
@@ -222,8 +222,12 @@ func (s *Server) RenderIndex(w http.ResponseWriter, r *http.Request, cr policy.C
|
|||||||
chall, err := s.issueChallenge(r.Context(), r, lg, cr, rule)
|
chall, err := s.issueChallenge(r.Context(), r, lg, cr, rule)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Error("can't get challenge", "err", err)
|
lg.Error("can't get challenge", "err", err)
|
||||||
|
algorithm := "unknown"
|
||||||
|
if rule.Challenge != nil {
|
||||||
|
algorithm = rule.Challenge.Algorithm
|
||||||
|
}
|
||||||
s.ClearCookie(w, CookieOpts{Name: anubis.TestCookieName, Host: r.Host})
|
s.ClearCookie(w, CookieOpts{Name: anubis.TestCookieName, Host: r.Host})
|
||||||
s.respondWithError(w, r, fmt.Sprintf("%s: %s", localizer.T("internal_server_error"), rule.Challenge.Algorithm), makeCode(err))
|
s.respondWithError(w, r, fmt.Sprintf("%s: %s", localizer.T("internal_server_error"), algorithm), makeCode(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,9 +252,13 @@ func (s *Server) RenderIndex(w http.ResponseWriter, r *http.Request, cr policy.C
|
|||||||
|
|
||||||
impl, ok := challenge.Get(chall.Method)
|
impl, ok := challenge.Get(chall.Method)
|
||||||
if !ok {
|
if !ok {
|
||||||
lg.Error("check failed", "err", "can't get algorithm", "algorithm", rule.Challenge.Algorithm)
|
algorithm := "unknown"
|
||||||
|
if rule.Challenge != nil {
|
||||||
|
algorithm = rule.Challenge.Algorithm
|
||||||
|
}
|
||||||
|
lg.Error("check failed", "err", "can't get algorithm", "algorithm", algorithm)
|
||||||
s.ClearCookie(w, CookieOpts{Name: anubis.TestCookieName, Host: r.Host})
|
s.ClearCookie(w, CookieOpts{Name: anubis.TestCookieName, Host: r.Host})
|
||||||
s.respondWithError(w, r, fmt.Sprintf("%s: %s", localizer.T("internal_server_error"), rule.Challenge.Algorithm), makeCode(err))
|
s.respondWithError(w, r, fmt.Sprintf("%s: %s", localizer.T("internal_server_error"), algorithm), makeCode(err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user