Skip to content

Commit 2859f03

Browse files
XeCopilot
andauthored
cmd/anubis: add rule hashes for admin-configured denials (#696)
* cmd/anubis: add rule hashes for admin-configured denials Closes #695 Signed-off-by: Xe Iaso <[email protected]> * cmd/anubis: remove theoretical nil pointer deference panic This won't actually happen in real life, but the code paths might change so we should be somewhat defensive. Co-authored-by: Copilot <[email protected]> --------- Signed-off-by: Xe Iaso <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent c3f5f1f commit 2859f03

File tree

5 files changed

+57
-7
lines changed

5 files changed

+57
-7
lines changed

cmd/anubis/index_templ.go

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/anubis/main.go

+29-2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ func main() {
114114
log.Fatal(err)
115115
}
116116

117+
fmt.Println("Rule error IDs:")
118+
for _, rule := range s.policy.Bots {
119+
if rule.Action != config.RuleDeny {
120+
continue
121+
}
122+
123+
hash, err := rule.Hash()
124+
if err != nil {
125+
log.Fatalf("can't calculate checksum of rule %s: %v", rule.Name, err)
126+
}
127+
128+
fmt.Printf("* %s: %s\n", rule.Name, hash)
129+
}
130+
fmt.Println()
131+
117132
mux := http.NewServeMux()
118133
xess.Mount(mux)
119134

@@ -229,7 +244,7 @@ type Server struct {
229244
}
230245

231246
func (s *Server) maybeReverseProxy(w http.ResponseWriter, r *http.Request) {
232-
cr := s.check(r)
247+
cr, rule := s.check(r)
233248
r.Header.Add("X-Anubis-Rule", cr.Name)
234249
r.Header.Add("X-Anubis-Action", string(cr.Rule))
235250
lg := slog.With(
@@ -272,7 +287,19 @@ func (s *Server) maybeReverseProxy(w http.ResponseWriter, r *http.Request) {
272287
case config.RuleDeny:
273288
clearCookie(w)
274289
lg.Info("explicit deny")
275-
templ.Handler(base("Oh noes!", errorPage("Access Denied")), templ.WithStatus(http.StatusOK)).ServeHTTP(w, r)
290+
if rule == nil {
291+
lg.Error("rule is nil, cannot calculate checksum")
292+
templ.Handler(base("Oh noes!", errorPage("Other internal server error (contact the admin)")), templ.WithStatus(http.StatusInternalServerError)).ServeHTTP(w, r)
293+
return
294+
}
295+
hash, err := rule.Hash()
296+
if err != nil {
297+
lg.Error("can't calculate checksum of rule", "err", err)
298+
templ.Handler(base("Oh noes!", errorPage("Other internal server error (contact the admin)")), templ.WithStatus(http.StatusInternalServerError)).ServeHTTP(w, r)
299+
return
300+
}
301+
lg.Debug("rule hash", "hash", hash)
302+
templ.Handler(base("Oh noes!", errorPage(fmt.Sprintf("Access Denied: error code %s", hash))), templ.WithStatus(http.StatusOK)).ServeHTTP(w, r)
276303
return
277304
case config.RuleChallenge:
278305
lg.Debug("challenge requested")

cmd/anubis/policy.go

+17-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@ type Bot struct {
3535
Action config.Rule `json:"action"`
3636
}
3737

38+
func (b Bot) Hash() (string, error) {
39+
var pathRex string
40+
if b.Path != nil {
41+
pathRex = b.Path.String()
42+
}
43+
var userAgentRex string
44+
if b.UserAgent != nil {
45+
userAgentRex = b.UserAgent.String()
46+
}
47+
48+
return sha256sum(fmt.Sprintf("%s::%s::%s", b.Name, pathRex, userAgentRex))
49+
}
50+
3851
func parseConfig(fin io.Reader, fname string) (*ParsedConfig, error) {
3952
var c config.Config
4053
if err := json.NewDecoder(fin).Decode(&c); err != nil {
@@ -110,20 +123,20 @@ func cr(name string, rule config.Rule) CheckResult {
110123
}
111124

112125
// Check evaluates the list of rules, and returns the result
113-
func (s *Server) check(r *http.Request) CheckResult {
126+
func (s *Server) check(r *http.Request) (CheckResult, *Bot) {
114127
for _, b := range s.policy.Bots {
115128
if b.UserAgent != nil {
116129
if b.UserAgent.MatchString(r.UserAgent()) {
117-
return cr("bot/"+b.Name, b.Action)
130+
return cr("bot/"+b.Name, b.Action), &b
118131
}
119132
}
120133

121134
if b.Path != nil {
122135
if b.Path.MatchString(r.URL.Path) {
123-
return cr("bot/"+b.Name, b.Action)
136+
return cr("bot/"+b.Name, b.Action), &b
124137
}
125138
}
126139
}
127140

128-
return cr("default/allow", config.RuleAllow)
141+
return cr("default/allow", config.RuleAllow), nil
129142
}

cmd/anubis/static/js/main.mjs.gz

0 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"bots": [
3+
{
4+
"name": "everything",
5+
"user_agent_regex": ".*",
6+
"action": "DENY"
7+
}
8+
],
9+
"dnsbl": false
10+
}

0 commit comments

Comments
 (0)