Compare commits

...

22 Commits
v2.9.3 ... main

Author SHA1 Message Date
dependabot[bot]
0d8d35889d
chore: bump github.com/go-acme/lego/v4 from 4.22.2 to 4.25.2 (#224) 2025-08-06 21:55:29 +02:00
vgdh
ef2b9f9e1b
docs: disable network access inside examples (#223) 2025-07-06 22:27:30 +02:00
dependabot[bot]
d83e436bbb
chore: bump golang.org/x/net from 0.37.0 to 0.38.0 (#219) 2025-04-17 01:46:09 +02:00
Fernandez Ludovic
00ebf584ff chore: update linter 2025-03-25 03:34:46 +01:00
Fernandez Ludovic
38dd4b1898 chore: update linter 2025-03-09 19:36:21 +01:00
Fernandez Ludovic
ece40e90d6 chore: update dependencies 2025-03-09 19:35:45 +01:00
Fernandez Ludovic
5e2a080d2a chore: publish Docker images in GHCR 2025-03-09 19:32:33 +01:00
Fernandez Ludovic
07decbb976 chore: restrict workflows 2025-03-09 19:32:33 +01:00
Fernandez Ludovic
9a7fa88d60 docs: update readme 2025-02-21 22:35:42 +01:00
Fernandez Ludovic
a32520bcba docs: update examples 2025-02-21 22:34:35 +01:00
Fernandez Ludovic
39b542952b docs: update documentation 2025-02-21 22:30:27 +01:00
Fernandez Ludovic
b0aafdcc54 docs: improve readme 2025-02-13 03:04:45 +01:00
Fernandez Ludovic
565e4316ca chore: linting 2025-02-13 03:03:12 +01:00
Fernandez Ludovic
961192eb9b chore: update dependencies and Go version 2025-02-13 03:00:13 +01:00
Fernandez Ludovic
1bd1c094f2 chore: update linter 2025-02-13 02:53:42 +01:00
Fernandez Ludovic
380fa0efda chore: update linter 2025-02-13 02:51:32 +01:00
Ludovic Fernandez
059bfd27eb
chore: update donation URL 2025-01-24 22:38:24 +01:00
Fernandez Ludovic
45954b02ca chore: update funding 2025-01-06 20:17:49 +01:00
dependabot[bot]
e1b924f614
chore: bump golang.org/x/crypto from 0.28.0 to 0.31.0 (#212) 2024-12-12 02:10:59 +01:00
Blackmoon
865dceddf9
docs: adds all counts to one sum (#211) 2024-12-06 13:12:30 +00:00
Fernandez Ludovic
172bd870c6 feat: improve binary size 2024-12-05 14:58:48 +01:00
Fernandez Ludovic
ee3231c879 docs: fix examples 2024-12-05 14:51:38 +01:00
36 changed files with 786 additions and 1609 deletions

1
.github/FUNDING.yml vendored
View File

@ -1,3 +1,4 @@
github: ldez
ko_fi: ldez_oss
liberapay: ldez
thanks_dev: u/gh/ldez

View File

@ -3,9 +3,10 @@ name: Go Matrix
on:
push:
branches:
- master
- main
pull_request:
branches:
- main
jobs:

View File

@ -3,9 +3,10 @@ name: Main
on:
push:
branches:
- master
- main
pull_request:
branches:
- main
jobs:
@ -14,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
env:
GO_VERSION: stable
GOLANGCI_LINT_VERSION: v1.62.2
GOLANGCI_LINT_VERSION: v2.0.1
CGO_ENABLED: 0
steps:
@ -33,7 +34,7 @@ jobs:
# https://golangci-lint.run/usage/install#other-ci
- name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }}
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION}
golangci-lint --version
- name: Make

View File

@ -42,12 +42,18 @@ jobs:
with:
go-version: ${{ env.GO_VERSION }}
- name: Docker Login
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
echo "${DOCKER_PASSWORD}" | docker login --username "${DOCKER_USERNAME}" --password-stdin
- name: dockerhub-login
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: ghcr-login
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

View File

@ -1,105 +1,108 @@
version: "2"
formatters:
enable:
- gci
- gofumpt
settings:
gofumpt:
extra-rules: true
linters:
enable-all: true
default: all
disable:
- exportloopref # deprecated
- sqlclosecheck # not relevant (SQL)
- rowserrcheck # not relevant (SQL)
- cyclop # duplicate of gocyclo
- lll
- dupl
- prealloc
- wsl
- nlreturn
- mnd
- testpackage
- paralleltest
- tparallel
- err113
- wrapcheck
- exhaustive
- exhaustruct
- varnamelen
- lll
- mnd
- nilnil
- nlreturn
- paralleltest
- prealloc
- rowserrcheck # not relevant (SQL)
- sqlclosecheck # not relevant (SQL)
- testpackage
- tparallel
- varnamelen
- wrapcheck
- wsl
settings:
depguard:
rules:
main:
deny:
- pkg: github.com/instana/testify
desc: not allowed
- pkg: github.com/pkg/errors
desc: Should be replaced by standard lib errors package
forbidigo:
forbid:
- pattern: ^print(ln)?$
- pattern: ^spew\.Print(f|ln)?$
- pattern: ^spew\.Dump$
funlen:
lines: -1
statements: 40
goconst:
min-len: 3
min-occurrences: 3
gocritic:
disabled-checks:
- sloppyReassign
- rangeValCopy
- octalLiteral
- paramTypeCombine # already handle by gofumpt.extra-rules
enabled-tags:
- diagnostic
- style
- performance
settings:
hugeParam:
sizeThreshold: 100
gocyclo:
min-complexity: 12
godox:
keywords:
- FIXME
gomoddirectives:
replace-allow-list:
- github.com/abbot/go-http-auth
- github.com/go-check/check
- github.com/gorilla/mux
- github.com/mailgun/minheap
- github.com/mailgun/multibuf
- github.com/jaguilar/vt100
gosec:
excludes:
- G204 # Subprocess launched with a potential tainted input or cmd arguments
- G301 # Expect directory permissions to be 0750 or less
- G306 # Expect WriteFile permissions to be 0600 or less
govet:
disable:
- fieldalignment
enable-all: true
misspell:
locale: US
linters-settings:
govet:
enable-all: true
disable:
- fieldalignment
gocyclo:
min-complexity: 12
goconst:
min-len: 3
min-occurrences: 3
misspell:
locale: US
gofumpt:
extra-rules: true
depguard:
exclusions:
presets:
- comments
rules:
main:
deny:
- pkg: "github.com/instana/testify"
desc: not allowed
- pkg: "github.com/pkg/errors"
desc: Should be replaced by standard lib errors package
funlen:
lines: -1
statements: 40
godox:
keywords:
- FIXME
gocritic:
enabled-tags:
- diagnostic
- style
- performance
disabled-checks:
- sloppyReassign
- rangeValCopy
- octalLiteral
- paramTypeCombine # already handle by gofumpt.extra-rules
settings:
hugeParam:
sizeThreshold: 100
forbidigo:
forbid:
- '^print(ln)?$'
- '^spew\.Print(f|ln)?$'
- '^spew\.Dump$'
gomoddirectives:
replace-allow-list:
- github.com/abbot/go-http-auth
- github.com/go-check/check
- github.com/gorilla/mux
- github.com/mailgun/minheap
- github.com/mailgun/multibuf
- github.com/jaguilar/vt100
gosec:
excludes:
- G204 # Subprocess launched with a potential tainted input or cmd arguments
- G301 # Expect directory permissions to be 0750 or less
- G306 # Expect WriteFile permissions to be 0600 or less
- linters:
- gochecknoglobals
- gochecknoinits
path: cmd/
- linters:
- tagalign
path: internal/traefikv[1-3]/
- path: (.+)\.go$
text: 'ST1000: at least one file in a package should have a package comment'
- path: (.+)\.go$
text: 'package-comments: should have a package comment'
issues:
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0
exclude:
- 'ST1000: at least one file in a package should have a package comment'
- 'package-comments: should have a package comment'
exclude-rules:
- path: cmd/
linters:
- gochecknoglobals
- gochecknoinits
output:
show-stats: true
sort-results: true
sort-order:
- linter
- file
run:
timeout: 5m

View File

@ -41,10 +41,10 @@ changelog:
archives:
- id: tcd
name_template: '{{ .ProjectName }}_v{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}'
format: tar.gz
formats: [ 'tar.gz' ]
format_overrides:
- goos: windows
format: zip
formats: [ 'zip' ]
files:
- LICENSE
@ -70,6 +70,27 @@ docker_manifests:
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv7'
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv6'
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-386'
- name_template: 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}'
image_templates:
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-amd64'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-arm64'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-armv7'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-armv6'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-386'
- name_template: 'ghcr.io/ldez/traefik-certs-dumper:latest'
image_templates:
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-amd64'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-arm64'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-armv7'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-armv6'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-386'
- name_template: 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}'
image_templates:
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-amd64'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-arm64'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv7'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv6'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-386'
dockers:
- use: buildx
@ -80,6 +101,9 @@ dockers:
- 'ldez/traefik-certs-dumper:latest-amd64'
- 'ldez/traefik-certs-dumper:{{ .Tag }}-amd64'
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-amd64'
- 'ghcr.io/ldez/traefik-certs-dumper:latest-amd64'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-amd64'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-amd64'
build_flag_templates:
- '--pull'
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
@ -103,6 +127,9 @@ dockers:
- 'ldez/traefik-certs-dumper:{{ .Tag }}-arm64'
- 'ldez/traefik-certs-dumper:{{ .Tag }}-arm.v8' # only for compatibility with Seihon
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-arm64'
- 'ghcr.io/ldez/traefik-certs-dumper:latest-arm64'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-arm64'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-arm64'
build_flag_templates:
- '--pull'
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
@ -127,6 +154,9 @@ dockers:
- 'ldez/traefik-certs-dumper:{{ .Tag }}-armv7'
- 'ldez/traefik-certs-dumper:{{ .Tag }}-arm.v7' # only for compatibility with Seihon
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv7'
- 'ghcr.io/ldez/traefik-certs-dumper:latest-armv7'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-armv7'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv7'
build_flag_templates:
- '--pull'
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
@ -151,6 +181,9 @@ dockers:
- 'ldez/traefik-certs-dumper:{{ .Tag }}-armv6'
- 'ldez/traefik-certs-dumper:{{ .Tag }}-arm.v6' # only for compatibility with Seihon
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv6'
- 'ghcr.io/ldez/traefik-certs-dumper:latest-armv6'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-armv6'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-armv6'
build_flag_templates:
- '--pull'
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys
@ -172,6 +205,9 @@ dockers:
- 'ldez/traefik-certs-dumper:latest-386'
- 'ldez/traefik-certs-dumper:{{ .Tag }}-386'
- 'ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-386'
- 'ghcr.io/ldez/traefik-certs-dumper:latest-386'
- 'ghcr.io/ldez/traefik-certs-dumper:{{ .Tag }}-386'
- 'ghcr.io/ldez/traefik-certs-dumper:v{{ .Major }}.{{ .Minor }}-386'
build_flag_templates:
- '--pull'
# https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys

View File

@ -209,8 +209,8 @@ func help() {
s := fmt.Sprintln(hStyle.Render("Request for Donation."))
s += `
I need your help!
Donations fund maintenance and development of traefik-certs-dumper.
Click on this link to donate: https://bento.me/ldez`
Donations fund the maintenance and development of traefik-certs-dumper.
Click on this link to donate: https://donate.ldez.dev`
log.Println(pStyle.Render(s))
log.SetFlags(log.LstdFlags | log.Lshortfile)

View File

@ -23,9 +23,9 @@ services:
- ./letsencrypt:/letsencrypt
traefik-certs-dumper:
image: ldez/traefik-certs-dumper:v2.8.1
image: ldez/traefik-certs-dumper:v2.9.3
entrypoint: sh -c '
; while ! [ -e /data/acme.json ]
while ! [ -e /data/acme.json ]
|| ! [ `jq ".Certificates | length" /data/acme.json` != 0 ]; do
sleep 1
; done
@ -33,6 +33,7 @@ services:
--source /data/acme.json --dest /data/certs'
volumes:
- ./letsencrypt:/data
network_mode: "none"
whoami:
image: traefik/whoami:v1.8.1

View File

@ -23,16 +23,17 @@ services:
- ./letsencrypt/:/letsencrypt
traefik-certs-dumper:
image: ldez/traefik-certs-dumper:v2.8.3
image: ldez/traefik-certs-dumper:v2.9.3
entrypoint: sh -c '
; while ! [ -e /data/acme.json ]
|| ! [ `jq ".[] | .Certificates | length" /data/acme.json` != 0 ]; do
while ! [ -e /data/acme.json ]
|| ! [ `jq ".[] | .Certificates | length" /data/acme.json | jq -s "add" ` != 0 ]; do
sleep 1
; done
&& traefik-certs-dumper file --version v2 --watch
--source /data/acme.json --dest /data/certs'
volumes:
- ./letsencrypt:/data
network_mode: "none"
whoami:
image: traefik/whoami:v1.8.1

View File

@ -24,8 +24,9 @@ Dump Let's Encrypt certificates from Traefik.
### SEE ALSO
* [traefik-certs-dumper completion](traefik-certs-dumper_completion.md) - Generate the autocompletion script for the specified shell
* [traefik-certs-dumper file](traefik-certs-dumper_file.md) - Dump the content of the "acme.json" file.
* [traefik-certs-dumper kv](traefik-certs-dumper_kv.md) - Dump the content of a KV store.
* [traefik-certs-dumper version](traefik-certs-dumper_version.md) - Display version
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -0,0 +1,40 @@
## traefik-certs-dumper completion
Generate the autocompletion script for the specified shell
### Synopsis
Generate the autocompletion script for traefik-certs-dumper for the specified shell.
See each sub-command's help for details on how to use the generated script.
### Options
```
-h, --help help for completion
```
### Options inherited from parent commands
```
--clean Clean destination folder before dumping content. (default true)
--config string config file (default is $HOME/.traefik-certs-dumper.yaml)
--crt-ext string The file extension of the generated certificates. (default ".crt")
--crt-name string The file name (without extension) of the generated certificates. (default "certificate")
--dest string Path to store the dump content. (default "./dump")
--domain-subdir Use domain as sub-directory.
--key-ext string The file extension of the generated private keys. (default ".key")
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
--post-hook string Execute a command only if changes occurs on the data source. (works only with the watch mode)
--watch Enable watching changes.
```
### SEE ALSO
* [traefik-certs-dumper](traefik-certs-dumper.md) - Dump Let's Encrypt certificates from Traefik.
* [traefik-certs-dumper completion bash](traefik-certs-dumper_completion_bash.md) - Generate the autocompletion script for bash
* [traefik-certs-dumper completion fish](traefik-certs-dumper_completion_fish.md) - Generate the autocompletion script for fish
* [traefik-certs-dumper completion powershell](traefik-certs-dumper_completion_powershell.md) - Generate the autocompletion script for powershell
* [traefik-certs-dumper completion zsh](traefik-certs-dumper_completion_zsh.md) - Generate the autocompletion script for zsh
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -0,0 +1,59 @@
## traefik-certs-dumper completion bash
Generate the autocompletion script for bash
### Synopsis
Generate the autocompletion script for the bash shell.
This script depends on the 'bash-completion' package.
If it is not installed already, you can install it via your OS's package manager.
To load completions in your current shell session:
source <(traefik-certs-dumper completion bash)
To load completions for every new session, execute once:
#### Linux:
traefik-certs-dumper completion bash > /etc/bash_completion.d/traefik-certs-dumper
#### macOS:
traefik-certs-dumper completion bash > $(brew --prefix)/etc/bash_completion.d/traefik-certs-dumper
You will need to start a new shell for this setup to take effect.
```
traefik-certs-dumper completion bash
```
### Options
```
-h, --help help for bash
--no-descriptions disable completion descriptions
```
### Options inherited from parent commands
```
--clean Clean destination folder before dumping content. (default true)
--config string config file (default is $HOME/.traefik-certs-dumper.yaml)
--crt-ext string The file extension of the generated certificates. (default ".crt")
--crt-name string The file name (without extension) of the generated certificates. (default "certificate")
--dest string Path to store the dump content. (default "./dump")
--domain-subdir Use domain as sub-directory.
--key-ext string The file extension of the generated private keys. (default ".key")
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
--post-hook string Execute a command only if changes occurs on the data source. (works only with the watch mode)
--watch Enable watching changes.
```
### SEE ALSO
* [traefik-certs-dumper completion](traefik-certs-dumper_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -0,0 +1,50 @@
## traefik-certs-dumper completion fish
Generate the autocompletion script for fish
### Synopsis
Generate the autocompletion script for the fish shell.
To load completions in your current shell session:
traefik-certs-dumper completion fish | source
To load completions for every new session, execute once:
traefik-certs-dumper completion fish > ~/.config/fish/completions/traefik-certs-dumper.fish
You will need to start a new shell for this setup to take effect.
```
traefik-certs-dumper completion fish [flags]
```
### Options
```
-h, --help help for fish
--no-descriptions disable completion descriptions
```
### Options inherited from parent commands
```
--clean Clean destination folder before dumping content. (default true)
--config string config file (default is $HOME/.traefik-certs-dumper.yaml)
--crt-ext string The file extension of the generated certificates. (default ".crt")
--crt-name string The file name (without extension) of the generated certificates. (default "certificate")
--dest string Path to store the dump content. (default "./dump")
--domain-subdir Use domain as sub-directory.
--key-ext string The file extension of the generated private keys. (default ".key")
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
--post-hook string Execute a command only if changes occurs on the data source. (works only with the watch mode)
--watch Enable watching changes.
```
### SEE ALSO
* [traefik-certs-dumper completion](traefik-certs-dumper_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -0,0 +1,47 @@
## traefik-certs-dumper completion powershell
Generate the autocompletion script for powershell
### Synopsis
Generate the autocompletion script for powershell.
To load completions in your current shell session:
traefik-certs-dumper completion powershell | Out-String | Invoke-Expression
To load completions for every new session, add the output of the above command
to your powershell profile.
```
traefik-certs-dumper completion powershell [flags]
```
### Options
```
-h, --help help for powershell
--no-descriptions disable completion descriptions
```
### Options inherited from parent commands
```
--clean Clean destination folder before dumping content. (default true)
--config string config file (default is $HOME/.traefik-certs-dumper.yaml)
--crt-ext string The file extension of the generated certificates. (default ".crt")
--crt-name string The file name (without extension) of the generated certificates. (default "certificate")
--dest string Path to store the dump content. (default "./dump")
--domain-subdir Use domain as sub-directory.
--key-ext string The file extension of the generated private keys. (default ".key")
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
--post-hook string Execute a command only if changes occurs on the data source. (works only with the watch mode)
--watch Enable watching changes.
```
### SEE ALSO
* [traefik-certs-dumper completion](traefik-certs-dumper_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -0,0 +1,61 @@
## traefik-certs-dumper completion zsh
Generate the autocompletion script for zsh
### Synopsis
Generate the autocompletion script for the zsh shell.
If shell completion is not already enabled in your environment you will need
to enable it. You can execute the following once:
echo "autoload -U compinit; compinit" >> ~/.zshrc
To load completions in your current shell session:
source <(traefik-certs-dumper completion zsh)
To load completions for every new session, execute once:
#### Linux:
traefik-certs-dumper completion zsh > "${fpath[1]}/_traefik-certs-dumper"
#### macOS:
traefik-certs-dumper completion zsh > $(brew --prefix)/share/zsh/site-functions/_traefik-certs-dumper
You will need to start a new shell for this setup to take effect.
```
traefik-certs-dumper completion zsh [flags]
```
### Options
```
-h, --help help for zsh
--no-descriptions disable completion descriptions
```
### Options inherited from parent commands
```
--clean Clean destination folder before dumping content. (default true)
--config string config file (default is $HOME/.traefik-certs-dumper.yaml)
--crt-ext string The file extension of the generated certificates. (default ".crt")
--crt-name string The file name (without extension) of the generated certificates. (default "certificate")
--dest string Path to store the dump content. (default "./dump")
--domain-subdir Use domain as sub-directory.
--key-ext string The file extension of the generated private keys. (default ".key")
--key-name string The file name (without extension) of the generated private keys. (default "privatekey")
--post-hook string Execute a command only if changes occurs on the data source. (works only with the watch mode)
--watch Enable watching changes.
```
### SEE ALSO
* [traefik-certs-dumper completion](traefik-certs-dumper_completion.md) - Generate the autocompletion script for the specified shell
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -15,7 +15,7 @@ traefik-certs-dumper file [flags]
```
-h, --help help for file
--source string Path to 'acme.json' file. (default "./acme.json")
--version string Traefik version. If empty use v1. Possible values: 'v2'.
--version string Traefik version. If empty use v1. Possible values: 'v2', 'v3'.
```
### Options inherited from parent commands
@ -37,4 +37,4 @@ traefik-certs-dumper file [flags]
* [traefik-certs-dumper](traefik-certs-dumper.md) - Dump Let's Encrypt certificates from Traefik.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -47,4 +47,4 @@ Dump the content of a KV store.
* [traefik-certs-dumper kv etcd](traefik-certs-dumper_kv_etcd.md) - Dump the content of etcd.
* [traefik-certs-dumper kv zookeeper](traefik-certs-dumper_kv_zookeeper.md) - Dump the content of zookeeper.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -49,4 +49,4 @@ traefik-certs-dumper kv boltdb [flags]
* [traefik-certs-dumper kv](traefik-certs-dumper_kv.md) - Dump the content of a KV store.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -48,4 +48,4 @@ traefik-certs-dumper kv consul [flags]
* [traefik-certs-dumper kv](traefik-certs-dumper_kv.md) - Dump the content of a KV store.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -49,4 +49,4 @@ traefik-certs-dumper kv etcd [flags]
* [traefik-certs-dumper kv](traefik-certs-dumper_kv.md) - Dump the content of a KV store.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -47,4 +47,4 @@ traefik-certs-dumper kv zookeeper [flags]
* [traefik-certs-dumper kv](traefik-certs-dumper_kv.md) - Dump the content of a KV store.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -2,10 +2,6 @@
Display version
### Synopsis
Display version
```
traefik-certs-dumper version [flags]
```
@ -35,4 +31,4 @@ traefik-certs-dumper version [flags]
* [traefik-certs-dumper](traefik-certs-dumper.md) - Dump Let's Encrypt certificates from Traefik.
###### Auto generated by spf13/cobra on 9-Oct-2019
###### Auto generated by spf13/cobra on 21-Feb-2025

View File

@ -19,8 +19,9 @@ import (
dumperv2 "github.com/ldez/traefik-certs-dumper/v2/dumper/v2"
dumperv3 "github.com/ldez/traefik-certs-dumper/v2/dumper/v3"
"github.com/ldez/traefik-certs-dumper/v2/hook"
acmev2 "github.com/traefik/traefik/v2/pkg/provider/acme"
acmev3 "github.com/traefik/traefik/v3/pkg/provider/acme"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv1"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv2"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv3"
)
// Dump Dumps "acme.json" file to certificates.
@ -76,7 +77,7 @@ func dump(acmeFile string, baseConfig *dumper.BaseConfig) error {
}
func dumpV1(acmeFile string, baseConfig *dumper.BaseConfig) error {
data := &dumperv1.StoredData{}
data := &traefikv1.StoredData{}
err := readJSONFile(acmeFile, data)
if err != nil {
return err
@ -86,7 +87,7 @@ func dumpV1(acmeFile string, baseConfig *dumper.BaseConfig) error {
}
func dumpV2(acmeFile string, baseConfig *dumper.BaseConfig) error {
data := map[string]*acmev2.StoredData{}
data := map[string]*traefikv2.StoredData{}
err := readJSONFile(acmeFile, &data)
if err != nil {
return err
@ -96,7 +97,7 @@ func dumpV2(acmeFile string, baseConfig *dumper.BaseConfig) error {
}
func dumpV3(acmeFile string, baseConfig *dumper.BaseConfig) error {
data := map[string]*acmev3.StoredData{}
data := map[string]*traefikv3.StoredData{}
err := readJSONFile(acmeFile, &data)
if err != nil {
return err

View File

@ -1,7 +1,6 @@
package file
import (
"context"
"testing"
"github.com/ldez/traefik-certs-dumper/v2/dumper"
@ -54,7 +53,7 @@ func TestDump(t *testing.T) {
Version: test.version,
}
err := Dump(context.Background(), test.acmeFile, cfg)
err := Dump(t.Context(), test.acmeFile, cfg)
require.NoError(t, err)
})
}

View File

@ -3,7 +3,7 @@ package kv
import (
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/registration"
v1 "github.com/ldez/traefik-certs-dumper/v2/dumper/v1"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv1"
)
// CertificateOld is used to store certificate info.
@ -39,14 +39,14 @@ type ChallengeCert struct {
// DomainsCertificate contains a certificate for multiple domains.
type DomainsCertificate struct {
Domains v1.Domain
Domains traefikv1.Domain
Certificate *CertificateOld
}
// convertOldAccount converts account information from old account format.
func convertOldAccount(account *AccountOld) *v1.StoredData {
storedData := &v1.StoredData{
Account: &v1.Account{
func convertOldAccount(account *AccountOld) *traefikv1.StoredData {
storedData := &traefikv1.StoredData{
Account: &traefikv1.Account{
PrivateKey: account.PrivateKey,
Registration: account.Registration,
Email: account.Email,
@ -54,9 +54,9 @@ func convertOldAccount(account *AccountOld) *v1.StoredData {
},
}
var certs []*v1.Certificate
var certs []*traefikv1.Certificate
for _, oldCert := range account.DomainsCertificate.Certs {
certs = append(certs, &v1.Certificate{
certs = append(certs, &traefikv1.Certificate{
Certificate: oldCert.Certificate.Certificate,
Domain: oldCert.Domains,
Key: oldCert.Certificate.PrivateKey,

View File

@ -16,6 +16,7 @@ import (
"github.com/ldez/traefik-certs-dumper/v2/dumper"
v1 "github.com/ldez/traefik-certs-dumper/v2/dumper/v1"
"github.com/ldez/traefik-certs-dumper/v2/hook"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv1"
)
// DefaultStoreKeySuffix is the default suffix/storage.
@ -76,7 +77,7 @@ func dumpPair(pair *store.KVPair, baseConfig *dumper.BaseConfig) error {
return v1.Dump(data, baseConfig)
}
func getStoredDataFromGzip(pair *store.KVPair) (*v1.StoredData, error) {
func getStoredDataFromGzip(pair *store.KVPair) (*traefikv1.StoredData, error) {
reader, err := gzip.NewReader(bytes.NewBuffer(pair.Value))
if err != nil {
return nil, fmt.Errorf("fail to create GZip reader: %w", err)

View File

@ -8,6 +8,7 @@ import (
"github.com/go-acme/lego/v4/certcrypto"
"github.com/ldez/traefik-certs-dumper/v2/dumper"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv1"
)
const (
@ -16,7 +17,7 @@ const (
)
// Dump Dumps data to certificates.
func Dump(data *StoredData, baseConfig *dumper.BaseConfig) error {
func Dump(data *traefikv1.StoredData, baseConfig *dumper.BaseConfig) error {
if baseConfig.Clean {
err := cleanDir(baseConfig.DumpPath)
if err != nil {
@ -54,7 +55,7 @@ func Dump(data *StoredData, baseConfig *dumper.BaseConfig) error {
return os.WriteFile(filepath.Join(baseConfig.DumpPath, keysSubDir, "letsencrypt"+baseConfig.KeyInfo.Ext), privateKeyPem, 0o600)
}
func writeCert(dumpPath string, cert *Certificate, info dumper.FileInfo, domainSubDir bool) error {
func writeCert(dumpPath string, cert *traefikv1.Certificate, info dumper.FileInfo, domainSubDir bool) error {
certPath := filepath.Join(dumpPath, certsSubDir, safeName(cert.Domain.Main+info.Ext))
if domainSubDir {
certPath = filepath.Join(dumpPath, safeName(cert.Domain.Main), info.Name+info.Ext)
@ -66,7 +67,7 @@ func writeCert(dumpPath string, cert *Certificate, info dumper.FileInfo, domainS
return os.WriteFile(certPath, cert.Certificate, 0o666)
}
func writeKey(dumpPath string, cert *Certificate, info dumper.FileInfo, domainSubDir bool) error {
func writeKey(dumpPath string, cert *traefikv1.Certificate, info dumper.FileInfo, domainSubDir bool) error {
keyPath := filepath.Join(dumpPath, keysSubDir, safeName(cert.Domain.Main+info.Ext))
if domainSubDir {
keyPath = filepath.Join(dumpPath, safeName(cert.Domain.Main), info.Name+info.Ext)
@ -78,7 +79,7 @@ func writeKey(dumpPath string, cert *Certificate, info dumper.FileInfo, domainSu
return os.WriteFile(keyPath, cert.Key, 0o600)
}
func extractPEMPrivateKey(account *Account) []byte {
func extractPEMPrivateKey(account *traefikv1.Account) []byte {
var block *pem.Block
switch account.KeyType {
case certcrypto.RSA2048, certcrypto.RSA4096, certcrypto.RSA8192:

View File

@ -8,7 +8,7 @@ import (
"github.com/go-acme/lego/v4/certcrypto"
"github.com/ldez/traefik-certs-dumper/v2/dumper"
"github.com/traefik/traefik/v2/pkg/provider/acme"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv2"
)
const (
@ -17,7 +17,7 @@ const (
)
// Dump Dumps data to certificates.
func Dump(data map[string]*acme.StoredData, baseConfig *dumper.BaseConfig) error {
func Dump(data map[string]*traefikv2.StoredData, baseConfig *dumper.BaseConfig) error {
if baseConfig.Clean {
err := cleanDir(baseConfig.DumpPath)
if err != nil {
@ -63,7 +63,7 @@ func Dump(data map[string]*acme.StoredData, baseConfig *dumper.BaseConfig) error
return nil
}
func writeCert(dumpPath string, cert acme.Certificate, info dumper.FileInfo, domainSubDir bool) error {
func writeCert(dumpPath string, cert traefikv2.Certificate, info dumper.FileInfo, domainSubDir bool) error {
certPath := filepath.Join(dumpPath, certsSubDir, safeName(cert.Domain.Main+info.Ext))
if domainSubDir {
certPath = filepath.Join(dumpPath, safeName(cert.Domain.Main), info.Name+info.Ext)
@ -75,7 +75,7 @@ func writeCert(dumpPath string, cert acme.Certificate, info dumper.FileInfo, dom
return os.WriteFile(certPath, cert.Certificate, 0o666)
}
func writeKey(dumpPath string, cert acme.Certificate, info dumper.FileInfo, domainSubDir bool) error {
func writeKey(dumpPath string, cert traefikv2.Certificate, info dumper.FileInfo, domainSubDir bool) error {
keyPath := filepath.Join(dumpPath, keysSubDir, safeName(cert.Domain.Main+info.Ext))
if domainSubDir {
keyPath = filepath.Join(dumpPath, safeName(cert.Domain.Main), info.Name+info.Ext)
@ -87,7 +87,7 @@ func writeKey(dumpPath string, cert acme.Certificate, info dumper.FileInfo, doma
return os.WriteFile(keyPath, cert.Key, 0o600)
}
func extractPEMPrivateKey(account *acme.Account) []byte {
func extractPEMPrivateKey(account *traefikv2.Account) []byte {
var block *pem.Block
switch account.KeyType {
case certcrypto.RSA2048, certcrypto.RSA4096, certcrypto.RSA8192:

View File

@ -8,7 +8,7 @@ import (
"github.com/go-acme/lego/v4/certcrypto"
"github.com/ldez/traefik-certs-dumper/v2/dumper"
"github.com/traefik/traefik/v3/pkg/provider/acme"
"github.com/ldez/traefik-certs-dumper/v2/internal/traefikv3"
)
const (
@ -17,7 +17,7 @@ const (
)
// Dump Dumps data to certificates.
func Dump(data map[string]*acme.StoredData, baseConfig *dumper.BaseConfig) error {
func Dump(data map[string]*traefikv3.StoredData, baseConfig *dumper.BaseConfig) error {
if baseConfig.Clean {
err := cleanDir(baseConfig.DumpPath)
if err != nil {
@ -63,7 +63,7 @@ func Dump(data map[string]*acme.StoredData, baseConfig *dumper.BaseConfig) error
return nil
}
func writeCert(dumpPath string, cert acme.Certificate, info dumper.FileInfo, domainSubDir bool) error {
func writeCert(dumpPath string, cert traefikv3.Certificate, info dumper.FileInfo, domainSubDir bool) error {
certPath := filepath.Join(dumpPath, certsSubDir, safeName(cert.Domain.Main+info.Ext))
if domainSubDir {
certPath = filepath.Join(dumpPath, safeName(cert.Domain.Main), info.Name+info.Ext)
@ -75,7 +75,7 @@ func writeCert(dumpPath string, cert acme.Certificate, info dumper.FileInfo, dom
return os.WriteFile(certPath, cert.Certificate, 0o666)
}
func writeKey(dumpPath string, cert acme.Certificate, info dumper.FileInfo, domainSubDir bool) error {
func writeKey(dumpPath string, cert traefikv3.Certificate, info dumper.FileInfo, domainSubDir bool) error {
keyPath := filepath.Join(dumpPath, keysSubDir, safeName(cert.Domain.Main+info.Ext))
if domainSubDir {
keyPath = filepath.Join(dumpPath, safeName(cert.Domain.Main), info.Name+info.Ext)
@ -87,7 +87,7 @@ func writeKey(dumpPath string, cert acme.Certificate, info dumper.FileInfo, doma
return os.WriteFile(keyPath, cert.Key, 0o600)
}
func extractPEMPrivateKey(account *acme.Account) []byte {
func extractPEMPrivateKey(account *traefikv3.Account) []byte {
var block *pem.Block
switch account.KeyType {
case certcrypto.RSA2048, certcrypto.RSA4096, certcrypto.RSA8192:

228
go.mod
View File

@ -1,11 +1,11 @@
module github.com/ldez/traefik-certs-dumper/v2
go 1.23.0
go 1.24.0
require (
github.com/charmbracelet/lipgloss v1.0.0
github.com/fsnotify/fsnotify v1.8.0
github.com/go-acme/lego/v4 v4.20.4
github.com/fsnotify/fsnotify v1.9.0
github.com/go-acme/lego/v4 v4.25.2
github.com/kvtools/boltdb v1.0.2
github.com/kvtools/consul v1.0.2
github.com/kvtools/etcdv2 v1.0.2
@ -13,250 +13,78 @@ require (
github.com/kvtools/valkeyrie v1.0.0
github.com/kvtools/zookeeper v1.0.2
github.com/mitchellh/go-homedir v1.1.0
github.com/spf13/cobra v1.8.1
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.10.0
github.com/traefik/traefik/v2 v2.11.14
github.com/traefik/traefik/v3 v3.2.1
)
require (
cloud.google.com/go/auth v0.10.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.5 // indirect
cloud.google.com/go/compute/metadata v0.5.2 // indirect
github.com/AdamSLevy/jsonrpc2/v14 v14.1.0 // indirect
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph v0.9.0 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.29 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.22 // indirect
github.com/Azure/go-autorest/autorest/azure/auth v0.5.13 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/Azure/go-autorest/logger v0.2.1 // indirect
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.63.47 // indirect
github.com/armon/go-metrics v0.4.1 // indirect
github.com/aws/aws-sdk-go v1.44.327 // indirect
github.com/aws/aws-sdk-go-v2 v1.32.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.28.1 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.42 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.18 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.3 // indirect
github.com/aws/aws-sdk-go-v2/service/lightsail v1.42.3 // indirect
github.com/aws/aws-sdk-go-v2/service/route53 v1.46.0 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.3 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.32.3 // indirect
github.com/aws/smithy-go v1.22.0 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/benbjohnson/clock v1.3.0 // indirect
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/charmbracelet/x/ansi v0.4.2 // indirect
github.com/civo/civogo v0.3.11 // indirect
github.com/cloudflare/cloudflare-go v0.108.0 // indirect
github.com/containous/alice v0.0.0-20181107144136-d83ebdd94cbd // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cpu/goacmedns v0.1.1 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dimchansky/utfbom v1.1.1 // indirect
github.com/dnsimple/dnsimple-go v1.7.0 // indirect
github.com/exoscale/egoscale/v3 v3.1.7 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
github.com/go-kit/log v0.2.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.16.0 // indirect
github.com/go-resty/resty/v2 v2.13.1 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/go-zookeeper/zk v1.0.3 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/go-jose/go-jose/v4 v4.1.1 // indirect
github.com/go-zookeeper/zk v1.0.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/go-github/v28 v28.1.1 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/s2a-go v0.1.8 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.13.0 // indirect
github.com/gophercloud/gophercloud v1.14.1 // indirect
github.com/gophercloud/utils v0.0.0-20231010081019-80377eca5d56 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
github.com/hashicorp/consul/api v1.28.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-hclog v1.6.3 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/go-metrics v0.5.4 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.7.0 // indirect
github.com/hashicorp/golang-lru v1.0.2 // indirect
github.com/hashicorp/hcl v1.0.1-vault-5 // indirect
github.com/hashicorp/serf v0.10.1 // indirect
github.com/http-wasm/http-wasm-host-go v0.7.0 // indirect
github.com/huaweicloud/huaweicloud-sdk-go-v3 v0.1.120 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/hashicorp/serf v0.10.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jonboulle/clockwork v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
github.com/kolo/xmlrpc v0.0.0-20220921171641-a4b6fa1dd06b // indirect
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/labbsr0x/bindman-dns-webhook v1.0.2 // indirect
github.com/labbsr0x/goh v1.0.1 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/linode/linodego v1.42.0 // indirect
github.com/liquidweb/liquidweb-cli v0.6.9 // indirect
github.com/liquidweb/liquidweb-go v1.6.4 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/magiconair/properties v1.8.9 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/miekg/dns v1.1.62 // indirect
github.com/mimuret/golang-iij-dpf v0.9.1 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/muesli/termenv v0.15.2 // indirect
github.com/namedotcom/go v0.0.0-20180403034216-08470befbe04 // indirect
github.com/nrdcg/auroradns v1.1.0 // indirect
github.com/nrdcg/bunny-go v0.0.0-20240207213615-dde5bf4577a3 // indirect
github.com/nrdcg/desec v0.8.0 // indirect
github.com/nrdcg/dnspod-go v0.4.0 // indirect
github.com/nrdcg/freemyip v0.2.0 // indirect
github.com/nrdcg/goinwx v0.10.0 // indirect
github.com/nrdcg/mailinabox v0.2.0 // indirect
github.com/nrdcg/namesilo v0.2.1 // indirect
github.com/nrdcg/nodion v0.1.0 // indirect
github.com/nrdcg/porkbun v0.4.0 // indirect
github.com/nzdjb/go-metaname v1.0.0 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/oracle/oci-go-sdk/v65 v65.77.1 // indirect
github.com/ovh/go-ovh v1.6.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pires/go-proxyproto v0.6.1 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/pquerna/otp v1.4.0 // indirect
github.com/regfish/regfish-dnsapi-go v0.1.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rs/zerolog v1.29.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sacloud/api-client-go v0.2.10 // indirect
github.com/sacloud/go-http v0.1.8 // indirect
github.com/sacloud/iaas-api-go v1.12.0 // indirect
github.com/sacloud/packages-go v0.0.10 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.30 // indirect
github.com/selectel/domains-go v1.1.0 // indirect
github.com/selectel/go-selvpcclient/v3 v3.1.1 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9 // indirect
github.com/softlayer/softlayer-go v1.1.7 // indirect
github.com/softlayer/xmlrpc v0.0.0-20200409220501-5f089df7cb7e // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.7.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spiffe/go-spiffe/v2 v2.1.1 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1034 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1034 // indirect
github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/traefik/paerser v0.2.1 // indirect
github.com/transip/gotransip/v6 v6.26.0 // indirect
github.com/ultradns/ultradns-go-sdk v1.8.0-20241010134910-243eeec // indirect
github.com/unrolled/render v1.0.2 // indirect
github.com/vinyldns/go-vinyldns v0.9.16 // indirect
github.com/volcengine/volc-sdk-golang v1.0.183 // indirect
github.com/vulcand/predicate v1.2.0 // indirect
github.com/vultr/govultr/v3 v3.9.1 // indirect
github.com/yandex-cloud/go-genproto v0.0.0-20241101135610-76a0cfc1a773 // indirect
github.com/yandex-cloud/go-sdk v0.0.0-20241101143304-947cf519f6bd // indirect
github.com/zeebo/errs v1.2.2 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/api/v3 v3.5.14 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.14 // indirect
go.etcd.io/etcd/client/v2 v2.305.12 // indirect
go.etcd.io/etcd/client/v3 v3.5.14 // indirect
go.mongodb.org/mongo-driver v1.12.1 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect
go.opentelemetry.io/otel v1.29.0 // indirect
go.opentelemetry.io/otel/metric v1.29.0 // indirect
go.opentelemetry.io/otel/trace v1.29.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/ratelimit v0.3.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/crypto v0.28.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/mod v0.21.0 // indirect
golang.org/x/net v0.30.0 // indirect
golang.org/x/oauth2 v0.23.0 // indirect
golang.org/x/sync v0.8.0 // indirect
golang.org/x/sys v0.26.0 // indirect
golang.org/x/term v0.25.0 // indirect
golang.org/x/text v0.19.0 // indirect
golang.org/x/time v0.7.0 // indirect
golang.org/x/tools v0.25.0 // indirect
google.golang.org/api v0.204.0 // indirect
google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241015192408-796eee8c2d53 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
google.golang.org/grpc v1.67.1 // indirect
google.golang.org/protobuf v1.35.1 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.27.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/ns1/ns1-go.v2 v2.12.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
// Containous forks
replace (
github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e
github.com/go-check/check => github.com/containous/check v0.0.0-20170915194414-ca0bf163426a
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220627093034-b2dd784e613f
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
)
exclude github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible

1322
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,6 @@
package hook
import (
"context"
"testing"
)
@ -22,7 +21,7 @@ func Test_execute(t *testing.T) {
for _, test := range testCases {
t.Run(test.desc, func(t *testing.T) {
err := execute(context.Background(), test.command)
err := execute(t.Context(), test.command)
if err != nil {
t.Fatal(err)
}

View File

@ -1,4 +1,4 @@
package v1
package traefikv1
import (
"github.com/go-acme/lego/v4/certcrypto"

101
internal/traefikv2/acme.go Normal file
View File

@ -0,0 +1,101 @@
package traefikv2
import (
"crypto"
"crypto/x509"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/registration"
)
// StoredData represents the data managed by Store.
type StoredData struct {
Account *Account
Certificates []*CertAndStore
}
// Account is used to store lets encrypt registration info.
type Account struct {
Email string
Registration *registration.Resource
PrivateKey []byte
KeyType certcrypto.KeyType
}
// GetEmail returns email.
func (a *Account) GetEmail() string {
return a.Email
}
// GetRegistration returns lets encrypt registration resource.
func (a *Account) GetRegistration() *registration.Resource {
return a.Registration
}
// GetPrivateKey returns private key.
func (a *Account) GetPrivateKey() crypto.PrivateKey {
privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey)
if err != nil {
return nil
}
return privateKey
}
// CertAndStore allows mapping a TLS certificate to a TLS store.
type CertAndStore struct {
Certificate
Store string
}
// Certificate is a struct which contains all data needed from an ACME certificate.
type Certificate struct {
Domain Domain `json:"domain,omitempty" toml:"domain,omitempty" yaml:"domain,omitempty"`
Certificate []byte `json:"certificate,omitempty" toml:"certificate,omitempty" yaml:"certificate,omitempty"`
Key []byte `json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty"`
}
// Domain holds a domain name with SANs.
type Domain struct {
// Main defines the main domain name.
Main string `description:"Default subject name." json:"main,omitempty" toml:"main,omitempty" yaml:"main,omitempty"`
// SANs defines the subject alternative domain names.
SANs []string `description:"Subject alternative names." json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty"`
}
// ToStrArray convert a domain into an array of strings.
func (d *Domain) ToStrArray() []string {
var domains []string
if d.Main != "" {
domains = []string{d.Main}
}
return append(domains, d.SANs...)
}
// Set sets a domains from an array of strings.
func (d *Domain) Set(domains []string) {
if len(domains) > 0 {
d.Main = domains[0]
d.SANs = domains[1:]
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (d *Domain) DeepCopyInto(out *Domain) {
*out = *d
if d.SANs != nil {
in, out := &d.SANs, &out.SANs
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Domain.
func (d *Domain) DeepCopy() *Domain {
if d == nil {
return nil
}
out := new(Domain)
d.DeepCopyInto(out)
return out
}

101
internal/traefikv3/acme.go Normal file
View File

@ -0,0 +1,101 @@
package traefikv3
import (
"crypto"
"crypto/x509"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/registration"
)
// StoredData represents the data managed by Store.
type StoredData struct {
Account *Account
Certificates []*CertAndStore
}
// Account is used to store lets encrypt registration info.
type Account struct {
Email string
Registration *registration.Resource
PrivateKey []byte
KeyType certcrypto.KeyType
}
// GetEmail returns email.
func (a *Account) GetEmail() string {
return a.Email
}
// GetRegistration returns lets encrypt registration resource.
func (a *Account) GetRegistration() *registration.Resource {
return a.Registration
}
// GetPrivateKey returns private key.
func (a *Account) GetPrivateKey() crypto.PrivateKey {
privateKey, err := x509.ParsePKCS1PrivateKey(a.PrivateKey)
if err != nil {
return nil
}
return privateKey
}
// CertAndStore allows mapping a TLS certificate to a TLS store.
type CertAndStore struct {
Certificate
Store string
}
// Certificate is a struct which contains all data needed from an ACME certificate.
type Certificate struct {
Domain Domain `json:"domain,omitempty" toml:"domain,omitempty" yaml:"domain,omitempty"`
Certificate []byte `json:"certificate,omitempty" toml:"certificate,omitempty" yaml:"certificate,omitempty"`
Key []byte `json:"key,omitempty" toml:"key,omitempty" yaml:"key,omitempty"`
}
// Domain holds a domain name with SANs.
type Domain struct {
// Main defines the main domain name.
Main string `description:"Default subject name." json:"main,omitempty" toml:"main,omitempty" yaml:"main,omitempty"`
// SANs defines the subject alternative domain names.
SANs []string `description:"Subject alternative names." json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty"`
}
// ToStrArray convert a domain into an array of strings.
func (d *Domain) ToStrArray() []string {
var domains []string
if d.Main != "" {
domains = []string{d.Main}
}
return append(domains, d.SANs...)
}
// Set sets a domains from an array of strings.
func (d *Domain) Set(domains []string) {
if len(domains) > 0 {
d.Main = domains[0]
d.SANs = domains[1:]
}
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (d *Domain) DeepCopyInto(out *Domain) {
*out = *d
if d.SANs != nil {
in, out := &d.SANs, &out.SANs
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Domain.
func (d *Domain) DeepCopy() *Domain {
if d == nil {
return nil
}
out := new(Domain)
d.DeepCopyInto(out)
return out
}

View File

@ -18,16 +18,17 @@ If you appreciate this project:
- from file ("acme.json")
- from KV stores (Consul, Etcd, Zookeeper)
- Output formats:
- use domain as sub-directory (allow custom names and extensions)
- use domain as subdirectory (allow custom names and extensions)
- flat (domain as filename)
- Hook (only with watch mode and if the data source changes)
- Support Traefik v1, v2, and v3.
## Installation
### Download / CI Integration
```bash
curl -sfL https://raw.githubusercontent.com/ldez/traefik-certs-dumper/master/godownloader.sh | bash -s -- -b $(go env GOPATH)/bin v2.8.1
curl -sfL https://raw.githubusercontent.com/ldez/traefik-certs-dumper/master/godownloader.sh | bash -s -- -b $(go env GOPATH)/bin v2.9.3
```
<!--
@ -60,6 +61,7 @@ Examples:
- Traefik v1: [docker-compose](docs/docker-compose-traefik-v1.yml)
- Traefik v2: [docker-compose](docs/docker-compose-traefik-v2.yml)
- Traefik v3: TODO
## Usage
@ -72,7 +74,7 @@ Examples:
### Simple Dump
```console
$ traefik-certs-dumper file
$ traefik-certs-dumper file --version v3
dump
├──certs
│ └──my.domain.com.key
@ -84,7 +86,7 @@ dump
### Change source and destination
```console
$ traefik-certs-dumper file --source ./acme.json --dest ./dump/test
$ traefik-certs-dumper file --version v3 --source ./acme.json --dest ./dump/test
test
├──certs
│ └──my.domain.com.key
@ -96,7 +98,7 @@ test
### Use domain as sub-directory
```console
$ traefik-certs-dumper file --domain-subdir=true
$ traefik-certs-dumper file --version v3 --domain-subdir=true
dump
├──my.domain.com
│ ├──certificate.crt
@ -108,7 +110,7 @@ dump
#### Change file extension
```console
$ traefik-certs-dumper file --domain-subdir --crt-ext=.pem --key-ext=.pem
$ traefik-certs-dumper file --version v3 --domain-subdir --crt-ext=.pem --key-ext=.pem
dump
├──my.domain.com
│ ├──certificate.pem
@ -120,7 +122,7 @@ dump
#### Change file name
```console
$ traefik-certs-dumper file --domain-subdir --crt-name=fullchain --key-name=privkey
$ traefik-certs-dumper file --version v3 --domain-subdir --crt-name=fullchain --key-name=privkey
dump
├──my.domain.com
│ ├──fullchain.crt
@ -131,23 +133,21 @@ dump
## Hook
Hook can be a one liner passed as a string, or a file for more complex post-hook scenarios.
Hook can be a one-liner passed as a string, or a file for more complex post-hook scenarios.
For the former, create a file (ex: `hook.sh`) and mount it, then pass `sh hooksh` as a parameter to `--post-hook`.
Here is a docker-compose example:
```yml
version: '3.9'
services:
# ...
traefik-certs-dumper:
image: ldez/traefik-certs-dumper:v2.8.1
image: ldez/traefik-certs-dumper:v2.9.3
container_name: traefik-certs-dumper
entrypoint: sh -c '
; while ! [ -e /data/acme.json ]
|| ! [ `jq ".[] | .Certificates | length" /data/acme.json` != 0 ]; do
while ! [ -e /data/acme.json ]
|| ! [ `jq ".[] | .Certificates | length" /data/acme.json | jq -s "add" ` != 0 ]; do
sleep 1
; done
&& traefik-certs-dumper file --version v2 --watch