Skip to content

Commit

Permalink
Merge multiple PRs to create fork
Browse files Browse the repository at this point in the history
Add a nix devshell for go
compiles with go 1.20
Fix certmagic usage. Fixes joohoi#337
Updated to certmagic v0.20.
Don't convert static records to lowercase
Replace adduser with useradd

Signed-off-by: Joe Martin <[email protected]>
  • Loading branch information
jmartindf committed Jun 8, 2024
1 parent 1b84da8 commit 860b816
Show file tree
Hide file tree
Showing 17 changed files with 343 additions and 119 deletions.
13 changes: 13 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# ^ added for shellcheck and file-type detection

# Watch & reload direnv on change
watch_file devshell.toml

if [[ $(type -t use_flake) != function ]]; then
echo "ERROR: use_flake function missing."
echo "Please update direnv to v2.30.0 or later."
exit 1
fi
use flake
# use flake_env .
10 changes: 4 additions & 6 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@ jobs:
name: Lint Sourcecode
runs-on: ubuntu-latest
steps:

- name: Check out code
uses: actions/checkout@v4

- uses: actions/setup-go@v5
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.20'
cache: false

- name: Check out code
uses: actions/checkout@v4
- name: Run golangci-lint
uses: golangci/golangci-lint-action@v3
with:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ acme-dns.log
.vagrant
coverage.out
.idea/
dist/
/.direnv/
19 changes: 17 additions & 2 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ before:
# you may remove this if you don't need go generate
- go generate ./...
builds:
- env:
- CGO_ENABLED=0
- binary: acme-dns
env:
- CGO_ENABLED=1
goos:
- linux
- darwin
goarch:
- amd64
- arm64
checksum:
name_template: 'checksums.txt'
snapshot:
Expand All @@ -22,3 +26,14 @@ changelog:
exclude:
- '^docs:'
- '^test:'
archives:
- id: tgz
format: tar.gz
files:
- LICENSE
- README.md
- Dockerfile
- config.cfg
- acme-dns.service
signs:
- artifacts: checksum
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
FROM golang:1.22.4-alpine AS builder
LABEL maintainer="[email protected]"

RUN apk add -U --no-cache ca-certificates gcc musl-dev git

Expand All @@ -7,7 +8,6 @@ COPY . .

RUN CGO_ENABLED=1 go build -ldflags="-extldflags=-static" -tags sqlite_omit_load_extension


FROM scratch

COPY --from=builder /build/acme-dns /
Expand Down
59 changes: 44 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
[![Go](https://github.com/fritterhoff/acme-dns/actions/workflows/go_cov.yml/badge.svg)](https://github.com/fritterhoff/acme-dns/actions/workflows/go_cov.yml) [![codecov](https://codecov.io/gh/fritterhoff/acme-dns/branch/master/graph/badge.svg?token=NA6E3FJ5Z5)](https://codecov.io/gh/fritterhoff/acme-dns) [![Go Report Card](https://goreportcard.com/badge/github.com/fritterhoff/acme-dns)](https://goreportcard.com/report/github.com/fritterhoff/acme-dns)

# acme-dns
# jmartindf's version of acme-dns

A simplified DNS server with a RESTful HTTP API to provide a simple way to automate ACME DNS challenges.

## Why This Fork?

I created [this fork](https://git.desertflood.com/jmartindf/acme-dns) to fix a few bugs that haven't yet been fixed upstream, in [joohoi/acme-dns](https://github.com/joohoi/acme-dns).

- [#330](https://github.com/joohoi/acme-dns/issues/330) - README adduser command wrong
- [#337](https://github.com/joohoi/acme-dns/issues/337) - error message every 10 minutes about managing the server certificate

I applied three pending PRs:

- [#351](https://github.com/joohoi/acme-dns/pull/351) - Fix certmagic usage, from [maddes-b](https://github.com/maddes-b)
- [#346](https://github.com/joohoi/acme-dns/pull/346) - Don't convert static records to lowercase, from [max-privatevoid](https://github.com/max-privatevoid)
- [#336](https://github.com/joohoi/acme-dns/pull/336) - Replace adduser with useradd, from [ihmels](https://github.com/ihmels)

and stole a commit from [tjmullicani](https://github.com/tjmullicani), [15f802d](https://github.com/tjmullicani/acme-dns/commit/15f802df6cbf336f2f854b6239cfc0b70a81b739).

I started from a base of [fritterhoff/acme-dns](https://github.com/fritterhoff/acme-dns), then applied PR [#313](https://github.com/joohoi/acme-dns/pull/313) - Update golint, dependencies and get to sane state. This reverted some of fritterhoff's changes and brought the code tree closer to the source, but with much updated dependencies.

At some point, I'd also like to apply PR [#270](https://github.com/joohoi/acme-dns/pull/270) - Allow set-and-delete flow that is usually used by acme-clients.

Finally, I dropped in a Nix [devshell](https://numtide.github.io/devshell/) flake, to make sure everything built properly.

## Why?

Many DNS servers do not provide an API to enable automation for the ACME DNS challenges. Those which do, give the keys way too much power.
Expand Down Expand Up @@ -126,18 +145,28 @@ See the INSTALL section for information on how to do this.
go build
```

3. Move the built acme-dns binary to a directory in your $PATH, for example:
`sudo mv acme-dns /usr/local/bin`
4. Edit config.cfg to suit your needs (see [configuration](#configuration)). `acme-dns` will read the configuration file from `/etc/acme-dns/config.cfg` or `./config.cfg`, or a location specified with the `-c` flag.
5. If your system has systemd, you can optionally install acme-dns as a service so that it will start on boot and be tracked by systemd. This also allows us to add the `CAP_NET_BIND_SERVICE` capability so that acme-dns can be run by a user other than root.
1. Make sure that you have moved the configuration file to `/etc/acme-dns/config.cfg` so that acme-dns can access it globally.
2. Move the acme-dns executable from `~/go/bin/acme-dns` to `/usr/local/bin/acme-dns` (Any location will work, just be sure to change `acme-dns.service` to match).
3. Create a minimal acme-dns user: `sudo adduser --system --gecos "acme-dns Service" --disabled-password --group --home /var/lib/acme-dns acme-dns`.
4. Move the systemd service unit from `acme-dns.service` to `/etc/systemd/system/acme-dns.service`.
5. Reload systemd units: `sudo systemctl daemon-reload`.
6. Enable acme-dns on boot: `sudo systemctl enable acme-dns.service`.
7. Run acme-dns: `sudo systemctl start acme-dns.service`.
6. If you did not install the systemd service, run `acme-dns`. Please note that acme-dns needs to open a privileged port (53, domain), so it needs to be run with elevated privileges.
3) Move the built acme-dns binary to a directory in your $PATH, for example:
`sudo mv acme-dns /usr/local/bin`

4) Edit config.cfg to suit your needs (see [configuration](#configuration)). `acme-dns` will read the configuration file from `/etc/acme-dns/config.cfg` or `./config.cfg`, or a location specified with the `-c` flag.

5) If your system has systemd, you can optionally install acme-dns as a service so that it will start on boot and be tracked by systemd. This also allows us to add the `CAP_NET_BIND_SERVICE` capability so that acme-dns can be run by a user other than root.

1) Make sure that you have moved the configuration file to `/etc/acme-dns/config.cfg` so that acme-dns can access it globally.

2) Move the acme-dns executable from `~/go/bin/acme-dns` to `/usr/local/bin/acme-dns` (Any location will work, just be sure to change `acme-dns.service` to match).

3) Create a minimal acme-dns user: `sudo useradd --system --comment "acme-dns Service" --user-group --create-home --home /var/lib/acme-dns acme-dns`

4) Move the systemd service unit from `acme-dns.service` to `/etc/systemd/system/acme-dns.service`.

5) Reload systemd units: `sudo systemctl daemon-reload`.

6) Enable acme-dns on boot: `sudo systemctl enable acme-dns.service`.

7) Run acme-dns: `sudo systemctl start acme-dns.service`.

6) If you did not install the systemd service, run `acme-dns`. Please note that acme-dns needs to open a privileged port (53, domain), so it needs to be run with elevated privileges.

### Using Docker

Expand Down
35 changes: 13 additions & 22 deletions challengeprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package main

import (
"context"
"strings"

"github.com/libdns/libdns"
log "github.com/sirupsen/logrus"
"github.com/mholt/acmez/acme"
)

// ChallengeProvider implements go-acme/lego Provider interface which is used for ACME DNS challenge handling
Expand All @@ -18,29 +15,23 @@ func NewChallengeProvider(servers []*DNSServer) ChallengeProvider {
return ChallengeProvider{servers: servers}
}

func (c *ChallengeProvider) AppendRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error) {
var token string
for _, item := range recs {

log.WithFields(log.Fields{"name": item.Name, "value": item.Value, "type": item.Type}).Info("Attempting to set dns record")
if strings.Contains(item.Name, "acme-challenge") {
token = item.Value
break
}
}

// Present is used for making the ACME DNS challenge token available for DNS
func (c *ChallengeProvider) Present(ctx context.Context, challenge acme.Challenge) error {
for _, s := range c.servers {
s.PersonalKeyAuth = token
s.PersonalKeyAuth = challenge.DNS01KeyAuthorization()
}
return recs, nil
return nil
}

func (c *ChallengeProvider) DeleteRecords(ctx context.Context, zone string, recs []libdns.Record) ([]libdns.Record, error) {
for _, item := range recs {
log.WithFields(log.Fields{"name": item.Name, "value": item.Value, "type": item.Type}).Info("Attempting to unset dns record")
}
// CleanUp is called after the run to remove the ACME DNS challenge tokens from DNS records
func (c *ChallengeProvider) CleanUp(ctx context.Context, _ acme.Challenge) error {
for _, s := range c.servers {
s.PersonalKeyAuth = ""
}
return recs, nil
return nil
}

// Wait is a dummy function as we are just going to be ready to answer the challenge from the get-go
func (c *ChallengeProvider) Wait(_ context.Context, _ acme.Challenge) error {
return nil
}
20 changes: 10 additions & 10 deletions db.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ func getSQLiteStmt(s string) string {
}

func (d *acmedb) Init(engine string, connection string) error {
d.Lock()
defer d.Unlock()
d.Mutex.Lock()
defer d.Mutex.Unlock()
db, err := sql.Open(engine, connection)
if err != nil {
return err
Expand Down Expand Up @@ -171,8 +171,8 @@ func (d *acmedb) NewTXTValuesInTransaction(tx *sql.Tx, subdomain string) error {
}

func (d *acmedb) Register(afrom cidrslice) (ACMETxt, error) {
d.Lock()
defer d.Unlock()
d.Mutex.Lock()
defer d.Mutex.Unlock()
var err error
tx, err := d.DB.Begin()
// Rollback if errored, commit if not
Expand Down Expand Up @@ -210,8 +210,8 @@ func (d *acmedb) Register(afrom cidrslice) (ACMETxt, error) {
}

func (d *acmedb) GetByUsername(u uuid.UUID) (ACMETxt, error) {
d.Lock()
defer d.Unlock()
d.Mutex.Lock()
defer d.Mutex.Unlock()
var results []ACMETxt
getSQL := `
SELECT Username, Password, Subdomain, AllowFrom
Expand Down Expand Up @@ -248,8 +248,8 @@ func (d *acmedb) GetByUsername(u uuid.UUID) (ACMETxt, error) {
}

func (d *acmedb) GetTXTForDomain(domain string) ([]string, error) {
d.Lock()
defer d.Unlock()
d.Mutex.Lock()
defer d.Mutex.Unlock()
domain = sanitizeString(domain)
var txts []string
getSQL := `
Expand Down Expand Up @@ -282,8 +282,8 @@ func (d *acmedb) GetTXTForDomain(domain string) ([]string, error) {
}

func (d *acmedb) Update(a ACMETxtPost) error {
d.Lock()
defer d.Unlock()
d.Mutex.Lock()
defer d.Mutex.Unlock()
var err error
// Data in a is already sanitized
timenow := time.Now().Unix()
Expand Down
7 changes: 7 additions & 0 deletions devshell.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# https://numtide.github.io/devshell
[devshell]
packages = [
"go"
]
name = "acme-dns-dev"

2 changes: 1 addition & 1 deletion dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (d *DNSServer) Start(errorChannel chan error) {
// ParseRecords parses a slice of DNS record string
func (d *DNSServer) ParseRecords(config DNSConfig) {
for _, v := range config.General.StaticRecords {
rr, err := dns.NewRR(strings.ToLower(v))
rr, err := dns.NewRR(v)
if err != nil {
log.WithFields(log.Fields{"error": err.Error(), "rr": v}).Warning("Could not parse RR from config")
continue
Expand Down
Loading

0 comments on commit 860b816

Please sign in to comment.