79 Commits

Author SHA1 Message Date
dependabot[bot]
5a036a6638 build(deps): Bump actions/upload-artifact from 5.0.0 to 6.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5.0.0 to 6.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](330a01c490...b7c566a772)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-20 09:37:00 +01:00
dependabot[bot]
17f906df1e build(deps): Bump github/codeql-action from 4.31.8 to 4.31.9
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.8 to 4.31.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](1b168cd394...5d4e8d1aca)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-20 09:36:10 +01:00
dependabot[bot]
a73b625e68 build(deps): Bump github/codeql-action from 4.31.7 to 4.31.8
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.7 to 4.31.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](cf1bb45a27...1b168cd394)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-14 07:10:42 +01:00
dependabot[bot]
780ac71f74 build(deps): Bump wangyoucao577/go-release-action from 1.54 to 1.55
Bumps [wangyoucao577/go-release-action](https://github.com/wangyoucao577/go-release-action) from 1.54 to 1.55.
- [Release notes](https://github.com/wangyoucao577/go-release-action/releases)
- [Commits](ec4e3151b3...2794951026)

---
updated-dependencies:
- dependency-name: wangyoucao577/go-release-action
  dependency-version: '1.55'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-12 10:59:24 +01:00
dependabot[bot]
88b425b63d build(deps): Bump step-security/harden-runner from 2.13.3 to 2.14.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.3 to 2.14.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](df199fb7be...20cf305ff2)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.14.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-12 10:58:54 +01:00
dependabot[bot]
42c8136071 build(deps): Bump golang.org/x/crypto from 0.45.0 to 0.46.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.45.0 to 0.46.0.
- [Commits](https://github.com/golang/crypto/compare/v0.45.0...v0.46.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.46.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-09 17:27:04 +01:00
dependabot[bot]
b0dfe3e540 build(deps): Bump github/codeql-action from 4.31.6 to 4.31.7
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.6 to 4.31.7.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](fe4161a26a...cf1bb45a27)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 14:44:43 +01:00
dependabot[bot]
2cecffe562 build(deps): Bump wangyoucao577/go-release-action from 1.53 to 1.54
Bumps [wangyoucao577/go-release-action](https://github.com/wangyoucao577/go-release-action) from 1.53 to 1.54.
- [Release notes](https://github.com/wangyoucao577/go-release-action/releases)
- [Commits](481a2c1a0f...ec4e3151b3)

---
updated-dependencies:
- dependency-name: wangyoucao577/go-release-action
  dependency-version: '1.54'
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 14:44:16 +01:00
dependabot[bot]
b8f8214922 build(deps): Bump actions/checkout from 6.0.0 to 6.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](1af3b93b68...8e8c483db8)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-06 08:16:10 +01:00
dependabot[bot]
bc2e50b4d5 build(deps): Bump step-security/harden-runner from 2.13.2 to 2.13.3
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.2 to 2.13.3.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](95d9a5deda...df199fb7be)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.13.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-06 08:15:27 +01:00
dependabot[bot]
87976ae630 build(deps): Bump github/codeql-action from 4.31.4 to 4.31.6
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.4 to 4.31.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](e12f017898...fe4161a26a)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-06 08:15:02 +01:00
dependabot[bot]
ccb70f5cf6 build(deps): Bump actions/checkout from 5.0.1 to 6.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.1 to 6.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](93cb6efe18...1af3b93b68)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 14:30:52 +01:00
dependabot[bot]
0b6681b7dc build(deps): Bump actions/setup-go from 6.0.0 to 6.1.0
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 6.0.0 to 6.1.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](4469467582...4dc6199c7b)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 14:28:06 +01:00
dependabot[bot]
51a6fb7feb build(deps): Bump golang.org/x/crypto from 0.44.0 to 0.45.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.44.0 to 0.45.0.
- [Commits](https://github.com/golang/crypto/compare/v0.44.0...v0.45.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.45.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 05:56:48 +01:00
dependabot[bot]
7e38262340 build(deps): Bump github/codeql-action from 4.31.3 to 4.31.4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.3 to 4.31.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](014f16e7ab...e12f017898)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-20 05:55:59 +01:00
dependabot[bot]
0febc5a07a build(deps): Bump actions/checkout from 5.0.0 to 5.0.1
Bumps [actions/checkout](https://github.com/actions/checkout) from 5.0.0 to 5.0.1.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](08c6903cd8...93cb6efe18)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 5.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-18 13:13:45 +01:00
Bernhard Froehlich
6fce35c3f4 ci: Use latest go version for release builds 2025-11-15 07:28:50 +00:00
Bernhard Froehlich
1130c9b6b0 deps: Bump klauspost/compress to latest version 2025-11-15 07:27:50 +00:00
dependabot[bot]
515352042a build(deps): Bump golang.org/x/crypto from 0.43.0 to 0.44.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.43.0 to 0.44.0.
- [Commits](https://github.com/golang/crypto/compare/v0.43.0...v0.44.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.44.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-15 08:00:46 +01:00
dependabot[bot]
946bf5ec90 build(deps): Bump actions/dependency-review-action from 4.8.1 to 4.8.2
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.1 to 4.8.2.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](40c09b7dc9...3c4e3dcb1a)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-15 07:59:59 +01:00
dependabot[bot]
8245a2987d build(deps): Bump github/codeql-action from 4.31.2 to 4.31.3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.2 to 4.31.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](0499de31b9...014f16e7ab)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-15 07:59:27 +01:00
Aivars Sterns
d652d67542 fix: add simple doc 2025-11-08 08:20:02 +01:00
Aivars Sterns
ffc4db21e7 fix: add simple doc 2025-11-08 08:20:02 +01:00
Aivars Sterns
b0e4f0077f fix: add tests 2025-11-08 08:20:02 +01:00
Aivars Sterns
b164ce1387 feat: dynamic reread of aliases 2025-11-08 08:20:02 +01:00
Aivars Sterns
381a9b334b feat: add alias file support 2025-11-08 08:20:02 +01:00
Aivars Sterns
d1feaaabbf feat: add alias file support 2025-11-08 08:20:02 +01:00
Aivars Sterns
58a2324071 feat: add alias file support 2025-11-08 08:20:02 +01:00
Aivars Sterns
7b6be95125 feat: add alias file support 2025-11-08 08:20:02 +01:00
dependabot[bot]
6e9c00e171 build(deps): Bump step-security/harden-runner from 2.13.1 to 2.13.2
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.1 to 2.13.2.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](f4a75cfd61...95d9a5deda)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.13.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-06 10:40:27 +01:00
dependabot[bot]
20f87c889d build(deps): Bump github/codeql-action from 4.31.0 to 4.31.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.31.0 to 4.31.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](4e94bd11f7...0499de31b9)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-06 10:40:03 +01:00
dependabot[bot]
411e7171ea build(deps): Bump github/codeql-action from 4.30.9 to 4.31.0
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.9 to 4.31.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](16140ae1a1...4e94bd11f7)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.31.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-28 09:29:38 +01:00
dependabot[bot]
19de8da2ab build(deps): Bump actions/upload-artifact from 4.6.2 to 5.0.0
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.2 to 5.0.0.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](ea165f8d65...330a01c490)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-28 09:29:14 +01:00
dependabot[bot]
be6407c90f build(deps): Bump github/codeql-action from 4.30.8 to 4.30.9
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 4.30.8 to 4.30.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](f443b600d9...16140ae1a1)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.30.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-22 13:00:39 +02:00
dependabot[bot]
b77374bba1 build(deps): Bump github.com/DeRuina/timberjack from 1.3.7 to 1.3.9
Bumps [github.com/DeRuina/timberjack](https://github.com/DeRuina/timberjack) from 1.3.7 to 1.3.9.
- [Release notes](https://github.com/DeRuina/timberjack/releases)
- [Changelog](https://github.com/DeRuina/timberjack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DeRuina/timberjack/compare/v1.3.7...v1.3.9)

---
updated-dependencies:
- dependency-name: github.com/DeRuina/timberjack
  dependency-version: 1.3.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-22 12:57:10 +02:00
dependabot[bot]
35b43ac527 build(deps): Bump actions/dependency-review-action from 4.8.0 to 4.8.1
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.8.0 to 4.8.1.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](56339e523c...40c09b7dc9)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.8.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 16:46:53 +02:00
dependabot[bot]
8c3eef19f4 build(deps): Bump github/codeql-action from 3.30.6 to 4.30.8
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.6 to 4.30.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](64d10c1313...f443b600d9)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 4.30.8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 16:46:31 +02:00
dependabot[bot]
9440e63396 build(deps): Bump golang.org/x/crypto from 0.42.0 to 0.43.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.42.0 to 0.43.0.
- [Commits](https://github.com/golang/crypto/compare/v0.42.0...v0.43.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.43.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 16:46:12 +02:00
dependabot[bot]
e78d9f3bcf build(deps): Bump github/codeql-action from 3.30.5 to 3.30.6
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.5 to 3.30.6.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](3599b3baa1...64d10c1313)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-07 13:21:30 +02:00
dependabot[bot]
c0aaea9ae8 build(deps): Bump ossf/scorecard-action from 2.4.2 to 2.4.3
Bumps [ossf/scorecard-action](https://github.com/ossf/scorecard-action) from 2.4.2 to 2.4.3.
- [Release notes](https://github.com/ossf/scorecard-action/releases)
- [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md)
- [Commits](05b42c6244...4eaacf0543)

---
updated-dependencies:
- dependency-name: ossf/scorecard-action
  dependency-version: 2.4.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 15:04:56 +02:00
dependabot[bot]
f967b683b2 build(deps): Bump actions/dependency-review-action from 4.7.3 to 4.8.0
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.3 to 4.8.0.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](595b5aeba7...56339e523c)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 21:25:43 +02:00
dependabot[bot]
285f09bbb7 build(deps): Bump github/codeql-action from 3.30.3 to 3.30.5
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.3 to 3.30.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](192325c861...3599b3baa1)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 21:25:12 +02:00
dependabot[bot]
d9eadb04ae build(deps): Bump github.com/DeRuina/timberjack from 1.3.5 to 1.3.7
Bumps [github.com/DeRuina/timberjack](https://github.com/DeRuina/timberjack) from 1.3.5 to 1.3.7.
- [Release notes](https://github.com/DeRuina/timberjack/releases)
- [Changelog](https://github.com/DeRuina/timberjack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DeRuina/timberjack/compare/v1.3.5...v1.3.7)

---
updated-dependencies:
- dependency-name: github.com/DeRuina/timberjack
  dependency-version: 1.3.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-29 21:24:42 +02:00
dependabot[bot]
4057f8df89 build(deps): Bump github/codeql-action from 3.30.2 to 3.30.3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.2 to 3.30.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](d3678e237b...192325c861)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-11 17:02:24 +02:00
dependabot[bot]
6f2a184679 build(deps): Bump step-security/harden-runner from 2.13.0 to 2.13.1
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.13.0 to 2.13.1.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](ec9f2d5744...f4a75cfd61)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.13.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 12:46:05 +02:00
dependabot[bot]
4cf2fdc492 build(deps): Bump golang.org/x/crypto from 0.41.0 to 0.42.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.41.0 to 0.42.0.
- [Commits](https://github.com/golang/crypto/compare/v0.41.0...v0.42.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.42.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 12:45:35 +02:00
dependabot[bot]
5292f9e732 build(deps): Bump github/codeql-action from 3.30.1 to 3.30.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.1 to 3.30.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](f1f6e5f6af...d3678e237b)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-10 12:44:52 +02:00
dependabot[bot]
fec3776316 build(deps): Bump github/codeql-action from 3.30.0 to 3.30.1
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.30.0 to 3.30.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](2d92b76c45...f1f6e5f6af)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-08 20:41:54 +02:00
dependabot[bot]
e2d6d906e5 build(deps): Bump actions/setup-go from 5.5.0 to 6.0.0
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 5.5.0 to 6.0.0.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](d35c59abb0...4469467582)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-version: 6.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-05 14:13:27 +02:00
dependabot[bot]
c3c8f4f73d build(deps): Bump github/codeql-action from 3.29.11 to 3.30.0
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.11 to 3.30.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](3c3833e0f8...2d92b76c45)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-03 15:06:41 +02:00
dependabot[bot]
339bf2f3dd build(deps): Bump github.com/stretchr/testify from 1.11.0 to 1.11.1
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.11.0...v1.11.1)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-version: 1.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-28 14:09:00 +02:00
dependabot[bot]
07cda244b0 build(deps): Bump actions/dependency-review-action from 4.7.2 to 4.7.3
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.2 to 4.7.3.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](bc41886e18...595b5aeba7)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.7.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-27 22:18:17 +02:00
dependabot[bot]
eba80b7d48 build(deps): Bump github.com/stretchr/testify from 1.10.0 to 1.11.0
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.10.0...v1.11.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-26 10:07:01 +02:00
dependabot[bot]
b506a0e307 build(deps): Bump github/codeql-action from 3.29.10 to 3.29.11
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.10 to 3.29.11.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](96f518a34f...3c3833e0f8)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-25 08:07:31 +02:00
dependabot[bot]
79cd7fdf58 build(deps): Bump github.com/DeRuina/timberjack from 1.3.4 to 1.3.5
Bumps [github.com/DeRuina/timberjack](https://github.com/DeRuina/timberjack) from 1.3.4 to 1.3.5.
- [Release notes](https://github.com/DeRuina/timberjack/releases)
- [Changelog](https://github.com/DeRuina/timberjack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DeRuina/timberjack/compare/v1.3.4...v1.3.5)

---
updated-dependencies:
- dependency-name: github.com/DeRuina/timberjack
  dependency-version: 1.3.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 13:55:14 +02:00
dependabot[bot]
7b9d97cda5 build(deps): Bump github/codeql-action from 3.29.9 to 3.29.10
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.9 to 3.29.10.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](df559355d5...96f518a34f)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 13:53:21 +02:00
dependabot[bot]
b24970c378 build(deps): Bump actions/dependency-review-action from 4.7.1 to 4.7.2
Bumps [actions/dependency-review-action](https://github.com/actions/dependency-review-action) from 4.7.1 to 4.7.2.
- [Release notes](https://github.com/actions/dependency-review-action/releases)
- [Commits](da24556b54...bc41886e18)

---
updated-dependencies:
- dependency-name: actions/dependency-review-action
  dependency-version: 4.7.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 13:49:18 +02:00
dependabot[bot]
99c7d5db2d build(deps): Bump github/codeql-action from 3.29.8 to 3.29.9
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.8 to 3.29.9.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](76621b61de...df559355d5)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 13:47:49 +02:00
dependabot[bot]
3259232275 build(deps): Bump actions/checkout from 4.2.2 to 5.0.0
Bumps [actions/checkout](https://github.com/actions/checkout) from 4.2.2 to 5.0.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](11bd71901b...08c6903cd8)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 5.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-13 13:47:24 +02:00
Bernhard Fröhlich
d4077b9b5b Update scorecards.yml 2025-08-08 15:06:21 +02:00
Bernhard Fröhlich
0b2970ed90 Update codeql-analysis.yml 2025-08-08 15:06:21 +02:00
dependabot[bot]
19de223c55 build(deps): Bump github/codeql-action from 3.29.7 to 3.29.8
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.7 to 3.29.8.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](51f77329af...76621b61de)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-08 15:06:21 +02:00
dependabot[bot]
deb569552a build(deps): Bump golang.org/x/crypto from 0.40.0 to 0.41.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.40.0 to 0.41.0.
- [Commits](https://github.com/golang/crypto/compare/v0.40.0...v0.41.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.41.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-08 12:24:04 +02:00
dependabot[bot]
7a3d443754 build(deps): Bump github.com/DeRuina/timberjack from 1.3.3 to 1.3.4
Bumps [github.com/DeRuina/timberjack](https://github.com/DeRuina/timberjack) from 1.3.3 to 1.3.4.
- [Release notes](https://github.com/DeRuina/timberjack/releases)
- [Changelog](https://github.com/DeRuina/timberjack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/DeRuina/timberjack/compare/v1.3.3...v1.3.4)

---
updated-dependencies:
- dependency-name: github.com/DeRuina/timberjack
  dependency-version: 1.3.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-05 17:08:18 +02:00
Bernhard Froehlich
b78cc0a5c0 Cleanup getTLSConfig() and also remove custom cipher list
With modern Go (>=1.17) this is mostly a NOOP except CBC ciphers/
LUCKY13. Since Go has mitigations against LUCKY13 this in fact
improves our client compatbility and is safe to use.

See:	https://github.com/golang/go/issues/13385
2025-08-05 15:33:09 +02:00
Bernhard Froehlich
15bc75513a Fix go.mod for go test 2025-08-03 18:47:42 +02:00
Bernhard Froehlich
17421a539e Refactor to migrate from sirupsen/logrus to rs/zerolog and integrate DeRuina/timberjack for logfile rotation
Fixes #228
2025-08-03 18:47:42 +02:00
Bernhard Froehlich
1cb95f0265 Cleanup indirect dependencies and regenerate go.sum 2025-08-02 22:08:08 +02:00
dependabot[bot]
10f0f20004 build(deps): Bump github/codeql-action from 3.29.4 to 3.29.5
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.4 to 3.29.5.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](4e828ff8d4...51f77329af)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-30 13:14:34 +02:00
dependabot[bot]
843c02aa0e build(deps): Bump github/codeql-action from 3.29.3 to 3.29.4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.3 to 3.29.4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](d6bbdef45e...4e828ff8d4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-24 22:47:29 +02:00
dependabot[bot]
fcc77af3bc build(deps): Bump github/codeql-action from 3.29.2 to 3.29.3
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.2 to 3.29.3.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](181d5eefc2...d6bbdef45e)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-21 19:02:50 +02:00
dependabot[bot]
67bccd6fd8 build(deps): Bump step-security/harden-runner from 2.12.2 to 2.13.0
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.12.2 to 2.13.0.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](6c439dc8bd...ec9f2d5744)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-17 09:56:29 +02:00
dependabot[bot]
8f12438b5a build(deps): Bump golang.org/x/crypto from 0.39.0 to 0.40.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.39.0 to 0.40.0.
- [Commits](https://github.com/golang/crypto/compare/v0.39.0...v0.40.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.40.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-12 22:52:23 +02:00
dependabot[bot]
5b7a8ea783 build(deps): Bump github/codeql-action from 3.29.1 to 3.29.2
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.1 to 3.29.2.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](39edc492db...181d5eefc2)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-07-02 17:07:26 +02:00
dependabot[bot]
b715e23541 build(deps): Bump step-security/harden-runner from 2.12.1 to 2.12.2
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.12.1 to 2.12.2.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](002fdce3c6...6c439dc8bd)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.12.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-30 17:53:57 +02:00
dependabot[bot]
4e1cfa7bc6 build(deps): Bump github/codeql-action from 3.29.0 to 3.29.1
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.29.0 to 3.29.1.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](ce28f5bb42...39edc492db)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-30 17:53:24 +02:00
dependabot[bot]
9f7aa1719e build(deps): Bump step-security/harden-runner from 2.12.0 to 2.12.1
Bumps [step-security/harden-runner](https://github.com/step-security/harden-runner) from 2.12.0 to 2.12.1.
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](0634a2670c...002fdce3c6)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 22:12:59 +02:00
dependabot[bot]
692c1bd3ac build(deps): Bump github/codeql-action from 3.28.19 to 3.29.0
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3.28.19 to 3.29.0.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](fca7ace96b...ce28f5bb42)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: 3.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-12 22:12:18 +02:00
dependabot[bot]
638f6558cc build(deps): Bump golang.org/x/crypto from 0.38.0 to 0.39.0
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.38.0 to 0.39.0.
- [Commits](https://github.com/golang/crypto/compare/v0.38.0...v0.39.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-version: 0.39.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-06 21:48:53 +02:00
14 changed files with 737 additions and 208 deletions

View File

@@ -38,16 +38,16 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with: with:
egress-policy: audit egress-policy: audit
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 uses: github/codeql-action/init@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@@ -58,7 +58,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 uses: github/codeql-action/autobuild@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl # 📚 https://git.io/JvXDl
@@ -72,4 +72,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 uses: github/codeql-action/analyze@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9

View File

@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with: with:
egress-policy: audit egress-policy: audit
- name: 'Checkout Repository' - name: 'Checkout Repository'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: 'Dependency Review' - name: 'Dependency Review'
uses: actions/dependency-review-action@da24556b548a50705dd671f47852072ea4c105d9 # v4.7.1 uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4.8.2

View File

@@ -10,12 +10,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5.5.0 - uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with: with:
go-version: 'stable' go-version: 'stable'

View File

@@ -21,22 +21,21 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with: with:
egress-policy: audit egress-policy: audit
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Set APP_VERSION env - name: Set APP_VERSION env
run: echo APP_VERSION=$(echo ${GITHUB_REF} | rev | cut -d'/' -f 1 | rev ) >> ${GITHUB_ENV} run: echo APP_VERSION=$(echo ${GITHUB_REF} | rev | cut -d'/' -f 1 | rev ) >> ${GITHUB_ENV}
- name: Set BUILD_TIME env - name: Set BUILD_TIME env
run: echo BUILD_TIME=$(date) >> ${GITHUB_ENV} run: echo BUILD_TIME=$(date) >> ${GITHUB_ENV}
- uses: wangyoucao577/go-release-action@481a2c1a0f1be199722e3e9b74d7199acafc30a8 # v1.53 - uses: wangyoucao577/go-release-action@279495102627de7960cbc33434ab01a12bae144b # v1.55
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }} goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }} goarch: ${{ matrix.goarch }}
goversion: "1.24"
extra_files: LICENSE README.md smtprelay.ini extra_files: LICENSE README.md smtprelay.ini
ldflags: -s -w -X "main.appVersion=${{ env.APP_VERSION }}" -X "main.buildTime=${{ env.BUILD_TIME }}" ldflags: -s -w -X "main.appVersion=${{ env.APP_VERSION }}" -X "main.buildTime=${{ env.BUILD_TIME }}"

View File

@@ -36,17 +36,17 @@ jobs:
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0 uses: step-security/harden-runner@20cf305ff2072d973412fa9b1e3a4f227bda3c76 # v2.14.0
with: with:
egress-policy: audit egress-policy: audit
- name: "Checkout code" - name: "Checkout code"
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
with: with:
persist-credentials: false persist-credentials: false
- name: "Run analysis" - name: "Run analysis"
uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 uses: ossf/scorecard-action@4eaacf0543bb3f2c246792bd56e8cdeffafb205a # v2.4.3
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
@@ -68,7 +68,7 @@ jobs:
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
# format to the repository Actions tab. # format to the repository Actions tab.
- name: "Upload artifact" - name: "Upload artifact"
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif
@@ -76,6 +76,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard. # Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning" - name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 uses: github/codeql-action/upload-sarif@5d4e8d1aca955e8d8589aabd499c5cae939e33c7 # v4.31.9
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@@ -31,3 +31,4 @@ device which produces mail.
* Forwards all mail to a smarthost (any SMTP server) * Forwards all mail to a smarthost (any SMTP server)
* Small codebase * Small codebase
* IPv6 support * IPv6 support
* Aliases support (dynamic reload when alias file changes)

72
aliases.go Normal file
View File

@@ -0,0 +1,72 @@
package main
import (
"bufio"
"fmt"
"os"
"strings"
"sync"
)
type AliasMap map[string]string
var (
aliasesMutex sync.RWMutex
)
func AliasLoadFile(file string) (AliasMap, error) {
aliasMap := make(AliasMap)
count := 0
log.Info().
Str("file", file).
Msg("Loading aliases file")
f, err := os.Open(file)
if err != nil {
log.Fatal().
Str("file", file).
Err(err).
Msg("cannot load aliases file")
}
defer f.Close()
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
parts := strings.Fields(line)
if len(parts) >= 2 {
aliasMap[parts[0]] = parts[1]
count++
}
}
log.Info().
Str("file", file).
Msg(fmt.Sprintf("Loaded %d aliases from file", count))
if err := scanner.Err(); err != nil {
log.Fatal().
Str("file", file).
Err(err).
Msg("cannot load aliases file")
}
return aliasMap, nil
}
func LoadAliases(filename string) error {
newAliases, err := AliasLoadFile(filename)
if err != nil {
return err
}
aliasesMutex.Lock()
defer aliasesMutex.Unlock()
// Update the aliases map
aliasesList = newAliases
return nil
}

315
aliases_test.go Normal file
View File

@@ -0,0 +1,315 @@
package main
import (
"io"
"os"
"testing"
"github.com/rs/zerolog"
)
func init() {
// Initialize logger for tests to prevent nil pointer dereference
logger := zerolog.New(io.Discard).With().Timestamp().Logger()
log = &logger
}
func TestAliasLoadFile(t *testing.T) {
tests := []struct {
name string
content string
expected AliasMap
expectError bool
}{
{
name: "valid aliases",
content: "user1 alias1\nuser2 alias2\nuser3 alias3",
expected: AliasMap{
"user1": "alias1",
"user2": "alias2",
"user3": "alias3",
},
expectError: false,
},
{
name: "empty file",
content: "",
expected: AliasMap{},
expectError: false,
},
{
name: "file with empty lines",
content: "user1 alias1\n\nuser2 alias2\n\n",
expected: AliasMap{
"user1": "alias1",
"user2": "alias2",
},
expectError: false,
},
{
name: "file with whitespace",
content: " user1 alias1 \n\t user2\talias2\t",
expected: AliasMap{
"user1": "alias1",
"user2": "alias2",
},
expectError: false,
},
{
name: "extra fields ignored",
content: "user1 alias1 extra field\nuser2 alias2",
expected: AliasMap{
"user1": "alias1",
"user2": "alias2",
},
expectError: false,
},
{
name: "single field line ignored",
content: "user1\nuser2 alias2",
expected: AliasMap{"user2": "alias2"},
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
if _, err := tmpFile.WriteString(tt.content); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile.Close()
result, err := AliasLoadFile(tmpFile.Name())
if tt.expectError && err == nil {
t.Error("expected error but got none")
}
if !tt.expectError && err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(result) != len(tt.expected) {
t.Errorf("expected %d aliases, got %d", len(tt.expected), len(result))
}
for key, expectedValue := range tt.expected {
if actualValue, exists := result[key]; !exists {
t.Errorf("expected key %q not found", key)
} else if actualValue != expectedValue {
t.Errorf("for key %q: expected %q, got %q", key, expectedValue, actualValue)
}
}
})
}
}
func TestLoadAliases(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
content := "user1 alias1\nuser2 alias2"
if _, err := tmpFile.WriteString(content); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile.Close()
err = LoadAliases(tmpFile.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
aliasesMutex.RLock()
defer aliasesMutex.RUnlock()
if len(aliasesList) != 2 {
t.Errorf("expected 2 aliases, got %d", len(aliasesList))
}
if aliasesList["user1"] != "alias1" {
t.Errorf("expected user1 -> alias1, got %q", aliasesList["user1"])
}
if aliasesList["user2"] != "alias2" {
t.Errorf("expected user2 -> alias2, got %q", aliasesList["user2"])
}
}
func TestLoadAliases_EmptyFile(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
tmpFile.Close()
err = LoadAliases(tmpFile.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
aliasesMutex.RLock()
defer aliasesMutex.RUnlock()
if len(aliasesList) != 0 {
t.Errorf("expected 0 aliases, got %d", len(aliasesList))
}
}
func TestLoadAliases_UpdatesExistingAliases(t *testing.T) {
// First load
tmpFile1, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile1.Name())
content1 := "user1 alias1\nuser2 alias2"
if _, err := tmpFile1.WriteString(content1); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile1.Close()
err = LoadAliases(tmpFile1.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
// Second load with different content
tmpFile2, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile2.Name())
content2 := "user3 alias3"
if _, err := tmpFile2.WriteString(content2); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile2.Close()
err = LoadAliases(tmpFile2.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
aliasesMutex.RLock()
defer aliasesMutex.RUnlock()
if len(aliasesList) != 1 {
t.Errorf("expected 1 alias after reload, got %d", len(aliasesList))
}
if aliasesList["user3"] != "alias3" {
t.Errorf("expected user3 -> alias3, got %q", aliasesList["user3"])
}
if _, exists := aliasesList["user1"]; exists {
t.Error("expected user1 to be removed after reload")
}
}
func TestAliasLoadFile_MultipleSpaces(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
content := "user1 alias1\nuser2 alias2"
if _, err := tmpFile.WriteString(content); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile.Close()
result, err := AliasLoadFile(tmpFile.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if result["user1"] != "alias1" {
t.Errorf("expected user1 -> alias1, got %q", result["user1"])
}
if result["user2"] != "alias2" {
t.Errorf("expected user2 -> alias2, got %q", result["user2"])
}
}
func TestAliasLoadFile_TabSeparated(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
content := "user1\talias1\nuser2\t\talias2"
if _, err := tmpFile.WriteString(content); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile.Close()
result, err := AliasLoadFile(tmpFile.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(result) != 2 {
t.Errorf("expected 2 aliases, got %d", len(result))
}
}
func TestAliasLoadFile_DuplicateKeys(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
content := "user1 alias1\nuser1 alias2\nuser1 alias3"
if _, err := tmpFile.WriteString(content); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile.Close()
result, err := AliasLoadFile(tmpFile.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(result) != 1 {
t.Errorf("expected 1 alias (last one wins), got %d", len(result))
}
if result["user1"] != "alias3" {
t.Errorf("expected user1 -> alias3 (last one), got %q", result["user1"])
}
}
func TestAliasLoadFile_OnlyWhitespace(t *testing.T) {
tmpFile, err := os.CreateTemp("", "aliases-*.txt")
if err != nil {
t.Fatalf("failed to create temp file: %v", err)
}
defer os.Remove(tmpFile.Name())
content := " \n\t\t\n \t \n"
if _, err := tmpFile.WriteString(content); err != nil {
t.Fatalf("failed to write to temp file: %v", err)
}
tmpFile.Close()
result, err := AliasLoadFile(tmpFile.Name())
if err != nil {
t.Errorf("unexpected error: %v", err)
}
if len(result) != 0 {
t.Errorf("expected 0 aliases, got %d", len(result))
}
}

View File

@@ -12,7 +12,6 @@ import (
"time" "time"
"github.com/peterbourgon/ff/v3" "github.com/peterbourgon/ff/v3"
"github.com/sirupsen/logrus"
) )
var ( var (
@@ -43,6 +42,7 @@ var (
allowedSenderStr = flagset.String("allowed_sender", "", "Regular expression for valid FROM EMail addresses") allowedSenderStr = flagset.String("allowed_sender", "", "Regular expression for valid FROM EMail addresses")
allowedRecipStr = flagset.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses") allowedRecipStr = flagset.String("allowed_recipients", "", "Regular expression for valid TO EMail addresses")
allowedUsers = flagset.String("allowed_users", "", "Path to file with valid users/passwords") allowedUsers = flagset.String("allowed_users", "", "Path to file with valid users/passwords")
aliasFile = flagset.String("aliases_file", "", "Path to aliases file")
command = flagset.String("command", "", "Path to pipe command") command = flagset.String("command", "", "Path to pipe command")
remotesStr = flagset.String("remotes", "", "Outgoing SMTP servers") remotesStr = flagset.String("remotes", "", "Outgoing SMTP servers")
strictSender = flagset.Bool("strict_sender", false, "Use only SMTP servers with Sender matches to From") strictSender = flagset.Bool("strict_sender", false, "Use only SMTP servers with Sender matches to From")
@@ -60,28 +60,44 @@ var (
allowedSender *regexp.Regexp allowedSender *regexp.Regexp
allowedRecipients *regexp.Regexp allowedRecipients *regexp.Regexp
remotes = []*Remote{} remotes = []*Remote{}
aliasesList = AliasMap{}
) )
func localAuthRequired() bool { func localAuthRequired() bool {
return *allowedUsers != "" return *allowedUsers != ""
} }
func setupAliases() {
if *aliasFile != "" {
aliases := make(AliasMap)
aliases, err := AliasLoadFile(*aliasFile)
if err != nil {
log.Fatal().
Str("file", *aliasFile).
Err(err).
Msg("cannot load aliases file")
}
aliasesList = aliases
}
}
func setupAllowedNetworks() { func setupAllowedNetworks() {
for _, netstr := range splitstr(*allowedNetsStr, ' ') { for _, netstr := range splitstr(*allowedNetsStr, ' ') {
baseIP, allowedNet, err := net.ParseCIDR(netstr) baseIP, allowedNet, err := net.ParseCIDR(netstr)
if err != nil { if err != nil {
log.WithField("netstr", netstr). log.Fatal().
WithError(err). Str("netstr", netstr).
Fatal("Invalid CIDR notation in allowed_nets") Err(err).
Msg("Invalid CIDR notation in allowed_nets")
} }
// Reject any network specification where any host bits are set, // Reject any network specification where any host bits are set,
// meaning the address refers to a host and not a network. // meaning the address refers to a host and not a network.
if !allowedNet.IP.Equal(baseIP) { if !allowedNet.IP.Equal(baseIP) {
log.WithFields(logrus.Fields{ log.Fatal().
"given_net": netstr, Str("given_net", netstr).
"proper_net": allowedNet, Str("proper_net", allowedNet.String()).
}).Fatal("Invalid network in allowed_nets (host bits set)") Msg("Invalid network in allowed_nets (host bits set)")
} }
allowedNets = append(allowedNets, allowedNet) allowedNets = append(allowedNets, allowedNet)
@@ -94,30 +110,32 @@ func setupAllowedPatterns() {
if *allowedSenderStr != "" { if *allowedSenderStr != "" {
allowedSender, err = regexp.Compile(*allowedSenderStr) allowedSender, err = regexp.Compile(*allowedSenderStr)
if err != nil { if err != nil {
log.WithField("allowed_sender", *allowedSenderStr). log.Fatal().
WithError(err). Str("allowed_sender", *allowedSenderStr).
Fatal("allowed_sender pattern invalid") Err(err).
Msg("allowed_sender pattern invalid")
} }
} }
if *allowedRecipStr != "" { if *allowedRecipStr != "" {
allowedRecipients, err = regexp.Compile(*allowedRecipStr) allowedRecipients, err = regexp.Compile(*allowedRecipStr)
if err != nil { if err != nil {
log.WithField("allowed_recipients", *allowedRecipStr). log.Fatal().
WithError(err). Str("allowed_recipients", *allowedRecipStr).
Fatal("allowed_recipients pattern invalid") Err(err).
Msg("allowed_recipients pattern invalid")
} }
} }
} }
func setupRemotes() { func setupRemotes() {
logger := log.WithField("remotes", *remotesStr) logger := log.With().Str("remotes", *remotesStr).Logger()
if *remotesStr != "" { if *remotesStr != "" {
for _, remoteURL := range strings.Split(*remotesStr, " ") { for _, remoteURL := range strings.Split(*remotesStr, " ") {
r, err := ParseRemote(remoteURL) r, err := ParseRemote(remoteURL)
if err != nil { if err != nil {
logger.Fatal(fmt.Sprintf("error parsing url: '%s': %v", remoteURL, err)) logger.Fatal().Msg(fmt.Sprintf("error parsing url: '%s': %v", remoteURL, err))
} }
remotes = append(remotes, r) remotes = append(remotes, r)
@@ -148,8 +166,9 @@ func setupListeners() {
pa := splitProto(listenAddr) pa := splitProto(listenAddr)
if localAuthRequired() && pa.protocol == "" { if localAuthRequired() && pa.protocol == "" {
log.WithField("address", pa.address). log.Fatal().
Fatal("Local authentication (via allowed_users file) " + Str("address", pa.address).
Msg("Local authentication (via allowed_users file) " +
"not allowed with non-TLS listener") "not allowed with non-TLS listener")
} }
@@ -162,35 +181,41 @@ func setupTimeouts() {
readTimeout, err = time.ParseDuration(*readTimeoutStr) readTimeout, err = time.ParseDuration(*readTimeoutStr)
if err != nil { if err != nil {
log.WithField("read_timeout", *readTimeoutStr). log.Fatal().
WithError(err). Str("read_timeout", *readTimeoutStr).
Fatal("read_timeout duration string invalid") Err(err).
Msg("read_timeout duration string invalid")
} }
if readTimeout.Seconds() < 1 { if readTimeout.Seconds() < 1 {
log.WithField("read_timeout", *readTimeoutStr). log.Fatal().
Fatal("read_timeout less than one second") Str("read_timeout", *readTimeoutStr).
Msg("read_timeout less than one second")
} }
writeTimeout, err = time.ParseDuration(*writeTimeoutStr) writeTimeout, err = time.ParseDuration(*writeTimeoutStr)
if err != nil { if err != nil {
log.WithField("write_timeout", *writeTimeoutStr). log.Fatal().
WithError(err). Str("write_timeout", *writeTimeoutStr).
Fatal("write_timeout duration string invalid") Err(err).
Msg("write_timeout duration string invalid")
} }
if writeTimeout.Seconds() < 1 { if writeTimeout.Seconds() < 1 {
log.WithField("write_timeout", *writeTimeoutStr). log.Fatal().
Fatal("write_timeout less than one second") Str("write_timeout", *writeTimeoutStr).
Msg("write_timeout less than one second")
} }
dataTimeout, err = time.ParseDuration(*dataTimeoutStr) dataTimeout, err = time.ParseDuration(*dataTimeoutStr)
if err != nil { if err != nil {
log.WithField("data_timeout", *dataTimeoutStr). log.Fatal().
WithError(err). Str("data_timeout", *dataTimeoutStr).
Fatal("data_timeout duration string invalid") Err(err).
Msg("data_timeout duration string invalid")
} }
if dataTimeout.Seconds() < 1 { if dataTimeout.Seconds() < 1 {
log.WithField("data_timeout", *dataTimeoutStr). log.Fatal().
Fatal("data_timeout less than one second") Str("data_timeout", *dataTimeoutStr).
Msg("data_timeout less than one second")
} }
} }
@@ -226,11 +251,12 @@ func ConfigLoad() {
} }
if *remotesStr == "" && *command == "" { if *remotesStr == "" && *command == "" {
log.Warn("no remotes or command set; mail will not be forwarded!") log.Warn().Msg("no remotes or command set; mail will not be forwarded!")
} }
setupAllowedNetworks() setupAllowedNetworks()
setupAllowedPatterns() setupAllowedPatterns()
setupAliases()
setupRemotes() setupRemotes()
setupListeners() setupListeners()
setupTimeouts() setupTimeouts()

15
go.mod
View File

@@ -1,20 +1,23 @@
module github.com/decke/smtprelay module github.com/decke/smtprelay
require ( require (
github.com/DeRuina/timberjack v1.3.9
github.com/chrj/smtpd v0.3.1 github.com/chrj/smtpd v0.3.1
github.com/fsnotify/fsnotify v1.9.0
github.com/google/uuid v1.6.0 github.com/google/uuid v1.6.0
github.com/peterbourgon/ff/v3 v3.4.0 github.com/peterbourgon/ff/v3 v3.4.0
github.com/sirupsen/logrus v1.9.3 github.com/rs/zerolog v1.34.0
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.11.1
golang.org/x/crypto v0.38.0 golang.org/x/crypto v0.46.0
) )
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/klauspost/compress v1.18.1 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.39.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

57
go.sum
View File

@@ -1,39 +1,44 @@
github.com/DeRuina/timberjack v1.3.9 h1:6UXZ1I7ExPGTX/1UNYawR58LlOJUHKBPiYC7WQ91eBo=
github.com/DeRuina/timberjack v1.3.9/go.mod h1:RLoeQrwrCGIEF8gO5nV5b/gMD0QIy7bzQhBUgpp1EqE=
github.com/chrj/smtpd v0.3.1 h1:kogHFkbFdKaoH3bgZkqNC9uVtKYOFfM3uV3rroBdooE= github.com/chrj/smtpd v0.3.1 h1:kogHFkbFdKaoH3bgZkqNC9uVtKYOFfM3uV3rroBdooE=
github.com/chrj/smtpd v0.3.1/go.mod h1:JtABvV/LzvLmEIzy0NyDnrfMGOMd8wy5frAokwf6J9Q= github.com/chrj/smtpd v0.3.1/go.mod h1:JtABvV/LzvLmEIzy0NyDnrfMGOMd8wy5frAokwf6J9Q=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc=
github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@@ -2,59 +2,84 @@ package main
import ( import (
"fmt" "fmt"
"io"
"os" "os"
"strings"
"time" "time"
"github.com/sirupsen/logrus" "github.com/DeRuina/timberjack"
"github.com/rs/zerolog"
) )
var ( var (
log *logrus.Logger rotator *timberjack.Logger
log *zerolog.Logger
) )
func setupLogger() { func setupLogger() {
log = logrus.New() zerolog.TimeFieldFormat = time.RFC3339
// Handle logfile // Handle logfile
var writer io.Writer
if *logFile == "" { if *logFile == "" {
log.SetOutput(os.Stderr) writer = os.Stderr
} else { } else {
writer, err := os.OpenFile(*logFile, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0600) rotator = &timberjack.Logger{
if err != nil { Filename: *logFile,
fmt.Printf("cannot open log file: %s\n", err) MaxSize: 10, // megabytes before rotation
os.Exit(1) MaxBackups: 3,
MaxAge: 30, // days
Compress: true,
BackupTimeFormat: "20060102150405",
} }
writer = rotator
log.SetOutput(writer)
} }
// Handle log_format // Handle log_format
switch *logFormat { switch *logFormat {
case "json": case "json":
log.SetFormatter(&logrus.JSONFormatter{ // zerolog default is JSON
TimestampFormat: time.RFC3339Nano,
DisableHTMLEscape: true,
})
case "plain": case "plain":
log.SetFormatter(&logrus.TextFormatter{ writer = zerolog.ConsoleWriter{
DisableTimestamp: true, Out: writer,
}) NoColor: true,
TimeFormat: "",
FormatTimestamp: func(i interface{}) string {
return "" // avoid default time
},
}
case "", "default": case "", "default":
log.SetFormatter(&logrus.TextFormatter{ writer = zerolog.ConsoleWriter{
FullTimestamp: true, Out: writer,
}) NoColor: true,
TimeFormat: time.RFC3339,
}
case "pretty":
writer = zerolog.ConsoleWriter{
Out: writer,
TimeFormat: time.RFC3339Nano,
}
default: default:
fmt.Fprintf(os.Stderr, "Invalid log_format: %s\n", *logFormat) fmt.Fprintf(os.Stderr, "Invalid log_format: %s\n", *logFormat)
os.Exit(1) os.Exit(1)
} }
// Handle log_level l := zerolog.New(writer).With().Timestamp().Logger()
level, err := logrus.ParseLevel(*logLevel) log = &l
if err != nil {
level = logrus.InfoLevel
log.WithField("given_level", *logLevel). // Handle log_level
Warn("could not parse log level, defaulting to 'info'") level, err := zerolog.ParseLevel(strings.ToLower(*logLevel))
if err != nil {
level = zerolog.InfoLevel
log.Warn().Str("given_level", *logLevel).
Msg("could not parse log level, defaulting to 'info'")
}
zerolog.SetGlobalLevel(level)
}
// Call this on shutdown if you want to close the rotator and stop timers cleanly
func closeLogger() {
if rotator != nil {
rotator.Close()
} }
log.SetLevel(level)
} }

268
main.go
View File

@@ -13,8 +13,8 @@ import (
"syscall" "syscall"
"github.com/chrj/smtpd" "github.com/chrj/smtpd"
"github.com/fsnotify/fsnotify"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/sirupsen/logrus"
) )
func connectionChecker(peer smtpd.Peer) error { func connectionChecker(peer smtpd.Peer) error {
@@ -32,9 +32,9 @@ func connectionChecker(peer smtpd.Peer) error {
} }
} }
log.WithFields(logrus.Fields{ log.Warn().
"ip": peerIP, Str("ip", peerIP.String()).
}).Warn("Connection refused from address outside of allowed_nets") Msg("Connection refused from address outside of allowed_nets")
return smtpd.Error{Code: 421, Message: "Denied"} return smtpd.Error{Code: 421, Message: "Denied"}
} }
@@ -87,19 +87,21 @@ func senderChecker(peer smtpd.Peer, addr string) error {
user, err := AuthFetch(peer.Username) user, err := AuthFetch(peer.Username)
if err != nil { if err != nil {
// Shouldn't happen: authChecker already validated username+password // Shouldn't happen: authChecker already validated username+password
log.WithFields(logrus.Fields{ log.Warn().
"peer": peer.Addr, Str("peer", peer.Addr.String()).
"username": peer.Username, Str("username", peer.Username).
}).WithError(err).Warn("could not fetch auth user") Err(err).
Msg("could not fetch auth user")
return smtpd.Error{Code: 451, Message: "Bad sender address"} return smtpd.Error{Code: 451, Message: "Bad sender address"}
} }
if !addrAllowed(addr, user.allowedAddresses) { if !addrAllowed(addr, user.allowedAddresses) {
log.WithFields(logrus.Fields{ log.Warn().
"peer": peer.Addr, Str("peer", peer.Addr.String()).
"username": peer.Username, Str("username", peer.Username).
"sender_address": addr, Str("sender_address", addr).
}).Warn("sender address not allowed for authenticated user") Err(err).
Msg("sender address not allowed for authenticated user")
return smtpd.Error{Code: 451, Message: "Bad sender address"} return smtpd.Error{Code: 451, Message: "Bad sender address"}
} }
} }
@@ -114,10 +116,10 @@ func senderChecker(peer smtpd.Peer, addr string) error {
return nil return nil
} }
log.WithFields(logrus.Fields{ log.Warn().
"sender_address": addr, Str("sender_address", addr).
"peer": peer.Addr, Str("peer", peer.Addr.String()).
}).Warn("sender address not allowed by allowed_sender pattern") Msg("sender address not allowed by allowed_sender pattern")
return smtpd.Error{Code: 451, Message: "Bad sender address"} return smtpd.Error{Code: 451, Message: "Bad sender address"}
} }
@@ -132,20 +134,21 @@ func recipientChecker(peer smtpd.Peer, addr string) error {
return nil return nil
} }
log.WithFields(logrus.Fields{ log.Warn().
"peer": peer.Addr, Str("peer", peer.Addr.String()).
"recipient_address": addr, Str("recipient_address", addr).
}).Warn("recipient address not allowed by allowed_recipients pattern") Msg("recipient address not allowed by allowed_recipients pattern")
return smtpd.Error{Code: 451, Message: "Bad recipient address"} return smtpd.Error{Code: 451, Message: "Bad recipient address"}
} }
func authChecker(peer smtpd.Peer, username string, password string) error { func authChecker(peer smtpd.Peer, username string, password string) error {
err := AuthCheckPassword(username, password) err := AuthCheckPassword(username, password)
if err != nil { if err != nil {
log.WithFields(logrus.Fields{ log.Warn().
"peer": peer.Addr, Str("peer", peer.Addr.String()).
"username": username, Str("username", username).
}).WithError(err).Warn("auth error") Err(err).
Msg("auth error")
return smtpd.Error{Code: 535, Message: "Authentication credentials invalid"} return smtpd.Error{Code: 535, Message: "Authentication credentials invalid"}
} }
return nil return nil
@@ -157,12 +160,25 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
peerIP = addr.IP.String() peerIP = addr.IP.String()
} }
logger := log.WithFields(logrus.Fields{ // Check for aliases
"from": env.Sender, aliasesMutex.RLock()
"to": env.Recipients, for i, recipient := range env.Recipients {
"peer": peerIP, if alias, exists := aliasesList[recipient]; exists {
"uuid": generateUUID(), env.Recipients[i] = alias
}) log.Info().
Str("original_recipient", recipient).
Str("aliased_recipient", alias).
Msg("Recipient address aliased")
}
}
aliasesMutex.RUnlock()
logger := log.With().
Str("from", env.Sender).
Strs("to", env.Recipients).
Str("peer", peerIP).
Str("uuid", generateUUID()).
Logger()
var envRemotes []*Remote var envRemotes []*Remote
@@ -177,14 +193,14 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
} }
if len(envRemotes) == 0 && *command == "" { if len(envRemotes) == 0 && *command == "" {
logger.Warning("no remote_host or command set; discarding mail") logger.Warn().Msg("no remote_host or command set; discarding mail")
return smtpd.Error{Code: 554, Message: "There are no appropriate remote_host or command"} return smtpd.Error{Code: 554, Message: "There are no appropriate remote_host or command"}
} }
env.AddReceivedLine(peer) env.AddReceivedLine(peer)
if *command != "" { if *command != "" {
cmdLogger := logger.WithField("command", *command) cmdLogger := logger.With().Str("command", *command).Logger()
var stdout bytes.Buffer var stdout bytes.Buffer
var stderr bytes.Buffer var stderr bytes.Buffer
@@ -205,16 +221,16 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
err := cmd.Run() err := cmd.Run()
if err != nil { if err != nil {
cmdLogger.WithError(err).Error(stderr.String()) cmdLogger.Error().Err(err).Msg(stderr.String())
return smtpd.Error{Code: 554, Message: "External command failed"} return smtpd.Error{Code: 554, Message: "External command failed"}
} }
cmdLogger.Info("pipe command successful: " + stdout.String()) cmdLogger.Info().Msg("pipe command successful: " + stdout.String())
} }
for _, remote := range envRemotes { for _, remote := range envRemotes {
logger = logger.WithField("host", remote.Addr) logger = logger.With().Str("host", remote.Addr).Logger()
logger.Info("delivering mail from peer using smarthost") logger.Info().Msg("delivering mail from peer using smarthost")
err := SendMail( err := SendMail(
remote, remote,
@@ -229,21 +245,22 @@ func mailHandler(peer smtpd.Peer, env smtpd.Envelope) error {
case *textproto.Error: case *textproto.Error:
smtpError = smtpd.Error{Code: err.Code, Message: err.Msg} smtpError = smtpd.Error{Code: err.Code, Message: err.Msg}
logger.WithFields(logrus.Fields{ logger.Error().
"err_code": err.Code, Int("err_code", err.Code).
"err_msg": err.Msg, Str("err_msg", err.Msg).
}).Error("delivery failed") Msg("delivery failed")
default: default:
smtpError = smtpd.Error{Code: 421, Message: "Forwarding failed"} smtpError = smtpd.Error{Code: 421, Message: "Forwarding failed"}
logger.WithError(err). logger.Error().
Error("delivery failed") Err(err).
Msg("delivery failed")
} }
return smtpError return smtpError
} }
logger.Debug("delivery successful") logger.Debug().Msg("delivery successful")
} }
return nil return nil
@@ -253,8 +270,9 @@ func generateUUID() string {
uniqueID, err := uuid.NewRandom() uniqueID, err := uuid.NewRandom()
if err != nil { if err != nil {
log.WithError(err). log.Error().
Error("could not generate UUIDv4") Err(err).
Msg("could not generate UUIDv4")
return "" return ""
} }
@@ -263,64 +281,116 @@ func generateUUID() string {
} }
func getTLSConfig() *tls.Config { func getTLSConfig() *tls.Config {
// Ciphersuites as defined in stock Go but without 3DES and RC4
// https://golang.org/src/crypto/tls/cipher_suites.go
var tlsCipherSuites = []uint16{
tls.TLS_AES_128_GCM_SHA256,
tls.TLS_AES_256_GCM_SHA384,
tls.TLS_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_RSA_WITH_AES_128_GCM_SHA256, // does not provide PFS
tls.TLS_RSA_WITH_AES_256_GCM_SHA384, // does not provide PFS
}
if *localCert == "" || *localKey == "" { if *localCert == "" || *localKey == "" {
log.WithFields(logrus.Fields{ log.Fatal().
"cert_file": *localCert, Str("cert_file", *localCert).
"key_file": *localKey, Str("key_file", *localKey).
}).Fatal("TLS certificate/key file not defined in config") Msg("TLS certificate/key file not defined in config")
} }
cert, err := tls.LoadX509KeyPair(*localCert, *localKey) cert, err := tls.LoadX509KeyPair(*localCert, *localKey)
if err != nil { if err != nil {
log.WithField("error", err). log.Fatal().
Fatal("cannot load X509 keypair") Err(err).
Msg("cannot load X509 keypair")
} }
return &tls.Config{ return &tls.Config{
PreferServerCipherSuites: true, Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12, }
CipherSuites: tlsCipherSuites, }
Certificates: []tls.Certificate{cert},
func watchAliasFile() {
if *aliasFile == "" {
return
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Error().
Err(err).
Msg("failed to create file watcher for alias file")
return
}
go func() {
defer watcher.Close()
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Has(fsnotify.Write) || event.Has(fsnotify.Create) {
log.Info().
Str("file", event.Name).
Msg("alias file changed, reloading")
err := LoadAliases(*aliasFile)
if err != nil {
log.Error().
Str("file", *aliasFile).
Err(err).
Msg("failed to reload alias file")
} else {
log.Info().
Int("count", len(aliasesList)).
Msg("alias file reloaded successfully")
}
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Error().
Err(err).
Msg("file watcher error")
}
}
}()
err = watcher.Add(*aliasFile)
if err != nil {
log.Error().
Str("file", *aliasFile).
Err(err).
Msg("failed to watch alias file")
} else {
log.Info().
Str("file", *aliasFile).
Msg("watching alias file for changes")
} }
} }
func main() { func main() {
ConfigLoad() ConfigLoad()
log.WithField("version", appVersion). log.Debug().
Debug("starting smtprelay") Str("version", appVersion).
Msg("starting smtprelay")
// Load allowed users file // Load allowed users file
if localAuthRequired() { if localAuthRequired() {
err := AuthLoadFile(*allowedUsers) err := AuthLoadFile(*allowedUsers)
if err != nil { if err != nil {
log.WithField("file", *allowedUsers). log.Fatal().
WithError(err). Str("file", *allowedUsers).
Fatal("cannot load allowed users file") Err(err).
Msg("cannot load allowed users file")
} }
} }
// Start watching alias file for changes
watchAliasFile()
var servers []*smtpd.Server var servers []*smtpd.Server
// Create a server for each desired listen address // Create a server for each desired listen address
for _, listen := range listenAddrs { for _, listen := range listenAddrs {
logger := log.WithField("address", listen.address) logger := log.With().Str("address", listen.address).Logger()
server := &smtpd.Server{ server := &smtpd.Server{
Hostname: *hostName, Hostname: *hostName,
@@ -346,29 +416,32 @@ func main() {
switch listen.protocol { switch listen.protocol {
case "": case "":
logger.Info("listening on address") logger.Info().Msg("listening on address")
lsnr, err = net.Listen("tcp", listen.address) lsnr, err = net.Listen("tcp", listen.address)
case "starttls": case "starttls":
server.TLSConfig = getTLSConfig() server.TLSConfig = getTLSConfig()
server.ForceTLS = *localForceTLS server.ForceTLS = *localForceTLS
logger.Info("listening on address (STARTTLS)") logger.Info().Msg("listening on address (STARTTLS)")
lsnr, err = net.Listen("tcp", listen.address) lsnr, err = net.Listen("tcp", listen.address)
case "tls": case "tls":
server.TLSConfig = getTLSConfig() server.TLSConfig = getTLSConfig()
logger.Info("listening on address (TLS)") logger.Info().Msg("listening on address (TLS)")
lsnr, err = tls.Listen("tcp", listen.address, server.TLSConfig) lsnr, err = tls.Listen("tcp", listen.address, server.TLSConfig)
default: default:
logger.WithField("protocol", listen.protocol). logger.Fatal().
Fatal("unknown protocol in listen address") Str("protocol", listen.protocol).
Msg("unknown protocol in listen address")
} }
if err != nil { if err != nil {
logger.WithError(err).Fatal("error starting listener") logger.Fatal().
Err(err).
Msg("error starting listener")
} }
servers = append(servers, server) servers = append(servers, server)
@@ -381,27 +454,31 @@ func main() {
// First close the listeners // First close the listeners
for _, server := range servers { for _, server := range servers {
logger := log.WithField("address", server.Address()) logger := log.With().Str("address", server.Address().String()).Logger()
logger.Debug("Shutting down server") logger.Debug().Msg("Shutting down server")
err := server.Shutdown(false) err := server.Shutdown(false)
if err != nil { if err != nil {
logger.WithError(err). logger.Warn().
Warning("Shutdown failed") Err(err).
Msg("Shutdown failed")
} }
} }
// Then wait for the clients to exit // Then wait for the clients to exit
for _, server := range servers { for _, server := range servers {
logger := log.WithField("address", server.Address()) logger := log.With().Str("address", server.Address().String()).Logger()
logger.Debug("Waiting for server") logger.Debug().Msg("Waiting for server")
err := server.Wait() err := server.Wait()
if err != nil { if err != nil {
logger.WithError(err). logger.Warn().
Warning("Wait failed") Err(err).
Msg("Wait failed")
} }
} }
log.Debug("done") log.Debug().Msg("done")
closeLogger()
} }
func handleSignals() { func handleSignals() {
@@ -410,6 +487,7 @@ func handleSignals() {
signal.Notify(sigs, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM) signal.Notify(sigs, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
sig := <-sigs sig := <-sigs
log.WithField("signal", sig). log.Info().
Info("shutting down in response to received signal") Str("signal", sig.String()).
Msg("shutting down in response to received signal")
} }

View File

@@ -13,6 +13,11 @@
; Log level: panic, fatal, error, warn, info, debug, trace ; Log level: panic, fatal, error, warn, info, debug, trace
;log_level = info ;log_level = info
; path to alias file
; alias file format (separated by space):
; fake@email.tld real@email.tld
;aliases_file = aliases.txt
; Hostname for this SMTP server ; Hostname for this SMTP server
;hostname = localhost.localdomain ;hostname = localhost.localdomain