Guard: watch logs, ban misbehaving addresses in Housecarl
Files and the journal, patterns with one <IP>, bounties within a window, bans in a Housecarl ban list with repeat offenders' bans growing; presets for sshd, jarl, housecarl, steward, bind-xfr, postfix-sasl, dovecot, nginx-auth and housecarl-drops; guard run/check/test/status/bans/ban/unban; a Debian package with a sandboxed unit; an end-to-end test with Housecarl. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
d06bf8d531
47 files changed
+4614
No files matched your search
@@ -0,0 +1,150 @@
|
||||
// Package version holds Guard's version, set at build time with
|
||||
//
|
||||
// go build -ldflags "-X guard/internal/version.Version=1.2.3 -X guard/internal/version.Tag=v1.2.3"
|
||||
//
|
||||
// The Makefile sets Version from the VERSION file, and Tag only when the
|
||||
// build is of that release: HEAD is the tag v<VERSION> and no tracked file
|
||||
// is changed. Only such a build reports a version number. Other builds
|
||||
// are development builds, identified by their commit (which Go records
|
||||
// from git by itself) and by where they stand relative to the last tag
|
||||
// (Describe, from git describe).
|
||||
package version
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"runtime/debug"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Version is the Guard version (the VERSION file).
|
||||
var Version = "0.1.0-dev"
|
||||
|
||||
// Tag is the release tag the build is of ("" when it isn't a release).
|
||||
var Tag = ""
|
||||
|
||||
// Commit is the git commit the build is of. It is read from the build
|
||||
// information when not set at build time.
|
||||
var Commit = ""
|
||||
|
||||
// Describe is 'git describe --tags --long' of the build's commit
|
||||
// ("v0.2.0-rc.1-3-gca0f148b78b6"), set by the Makefile; it says how many
|
||||
// commits a development build is past the last tag.
|
||||
var Describe = ""
|
||||
|
||||
// Repo is Guard's source repository.
|
||||
const Repo = "https://gitea.adbraun.lol/adam/guard"
|
||||
|
||||
// Build describes what a binary was built from.
|
||||
type Build struct {
|
||||
Version string `json:"version"`
|
||||
Tag string `json:"tag,omitempty"`
|
||||
Commit string `json:"commit,omitempty"`
|
||||
Modified bool `json:"modified,omitempty"` // built with uncommitted changes
|
||||
// Since is the last tag before a development build's commit, and
|
||||
// Ahead how many commits the build is past it (0: the tag's commit,
|
||||
// with uncommitted changes).
|
||||
Since string `json:"since,omitempty"`
|
||||
Ahead int `json:"ahead,omitempty"`
|
||||
// Label is the short form to show: the tag of a release, otherwise
|
||||
// the abbreviated commit (or the version when the commit is unknown).
|
||||
Label string `json:"label"`
|
||||
// URL is the release or commit in the repository.
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
var info = sync.OnceValue(func() Build {
|
||||
commit, modified := Commit, false
|
||||
if bi, ok := debug.ReadBuildInfo(); ok {
|
||||
for _, s := range bi.Settings {
|
||||
switch s.Key {
|
||||
case "vcs.revision":
|
||||
if commit == "" {
|
||||
commit = s.Value
|
||||
}
|
||||
case "vcs.modified":
|
||||
modified = s.Value == "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
b := describe(Version, Tag, commit, modified)
|
||||
b.Since, b.Ahead = parseDescribe(Describe, b.Commit)
|
||||
return b
|
||||
})
|
||||
|
||||
// parseDescribe splits git describe --long output, if it is of commit.
|
||||
func parseDescribe(d, commit string) (since string, ahead int) {
|
||||
m := describeRe.FindStringSubmatch(d)
|
||||
if m == nil || commit == "" || !strings.HasPrefix(commit, m[3]) {
|
||||
return "", 0
|
||||
}
|
||||
n, _ := strconv.Atoi(m[2])
|
||||
return m[1], n
|
||||
}
|
||||
|
||||
var describeRe = regexp.MustCompile(`^(v.+)-(\d+)-g([0-9a-f]+)$`)
|
||||
|
||||
func describe(version, tag, commit string, modified bool) Build {
|
||||
b := Build{Version: version, Tag: tag, Commit: commit, Modified: modified}
|
||||
switch {
|
||||
case tag != "":
|
||||
b.Modified = false // the Makefile only sets Tag for clean trees
|
||||
b.Label, b.URL = tag, Repo+"/releases/tag/"+tag
|
||||
case commit != "":
|
||||
b.Label, b.URL = short(commit), Repo+"/commit/"+commit
|
||||
if modified {
|
||||
b.Label += "-modified"
|
||||
}
|
||||
default:
|
||||
b.Label, b.URL = version, Repo
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// Info describes this build.
|
||||
func Info() Build { return info() }
|
||||
|
||||
// String is the version for logs and 'version' commands. Only a release
|
||||
// build gives a version ("0.2.0"); any other build says it's a
|
||||
// development build: "dev a1b2c3d4e5f6 (3 commits after v0.2.0-rc.1)".
|
||||
func String() string { return Info().String() }
|
||||
|
||||
func (b Build) String() string {
|
||||
switch {
|
||||
case b.Tag != "":
|
||||
return b.Version
|
||||
case b.Commit == "":
|
||||
// No git information (built from a source archive).
|
||||
return b.Version + " (source build)"
|
||||
}
|
||||
s := "dev " + b.Label
|
||||
switch {
|
||||
case b.Since == "":
|
||||
case b.Ahead == 1:
|
||||
s += " (1 commit after " + b.Since + ")"
|
||||
case b.Ahead > 1:
|
||||
s += " (" + strconv.Itoa(b.Ahead) + " commits after " + b.Since + ")"
|
||||
case b.Modified:
|
||||
s += " (" + b.Since + " with uncommitted changes)"
|
||||
default:
|
||||
s += " (at " + b.Since + ")"
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Short is the version for a User-Agent: the version of a release,
|
||||
// otherwise the label ("a1b2c3d4e5f6").
|
||||
func Short() string {
|
||||
if b := Info(); b.Tag == "" && b.Commit != "" {
|
||||
return b.Label
|
||||
}
|
||||
return Version
|
||||
}
|
||||
|
||||
func short(commit string) string {
|
||||
if len(commit) > 12 {
|
||||
return commit[:12]
|
||||
}
|
||||
return commit
|
||||
}
|
||||
Reference in new issue
Block a user