Files
unkinben 00f5b4a246 initial commit: certmanager
migrate from python to golang
2026-03-24 19:38:24 +11:00

150 lines
3.7 KiB
Markdown

# certmanager
Vault PKI certificate issuance and SSH host key signing tool for Puppet-managed infrastructure.
Replaces the Python `certmanager` and `sshsignhost` scripts deployed by Puppet, compiled to a single static binary with no runtime dependencies.
## Installation
```sh
make build # produces ./certmanager
make install # installs to $GOPATH/bin
```
## Configuration
Config file is read from `$XDG_CONFIG_HOME/certmanager/config.yaml` (defaults to `~/.config/certmanager/config.yaml`). Override with `--config`.
On Puppet-managed nodes the config is written to `/opt/certmanager/config.yaml` by `profiles::helpers::certmanager`.
### Auth methods
#### AppRole (current — Puppet nodes)
```yaml
vault:
addr: https://vault.service.consul:8200
auth_method: approle
approle_path: approle # optional, defaults to "approle"
role_id: <role_id>
secret_id: <secret_id> # optional
mount_point: pki_int
role_name: servers_default
output_path: /tmp/certmanager
```
#### LDAP (testing / interactive use)
```yaml
vault:
addr: https://vault.service.consul:8200
auth_method: ldap
ldap_path: ldap # optional, defaults to "ldap"
ldap_username: alice
ldap_password: secret
mount_point: pki_int
role_name: servers_default
output_path: /tmp/certmanager
```
#### Kubernetes (Puppet running in-cluster)
```yaml
vault:
addr: https://vault.service.consul:8200
auth_method: kubernetes
kubernetes_path: kubernetes # optional, defaults to "kubernetes"
kubernetes_role: puppet
kubernetes_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token # optional
mount_point: pki_int
role_name: servers_default
output_path: /tmp/certmanager
```
#### Token (bootstrap / testing)
```yaml
vault:
addr: https://vault.service.consul:8200
auth_method: token
token: hvs.XXXX
mount_point: pki_int
role_name: servers_default
output_path: /tmp/certmanager
```
> **Note:** `auth_method` defaults to `approle` when omitted, preserving backwards compatibility with the existing Python script config format.
## Usage
### PKI certificate
```sh
# Write files to output_path/<common_name>/
certmanager pki host.example.com \
--alt-names host,host.example.com \
--ip-sans 127.0.0.1,10.0.0.1 \
--expiry-days 90
# JSON output (for use with Puppet generate())
certmanager pki host.example.com \
--alt-names host,host.example.com \
--ip-sans 127.0.0.1,10.0.0.1 \
--expiry-days 90 \
--json
```
Output files (written to `<output_path>/<common_name>/`):
| File | Contents |
|---|---|
| `certificate.crt` | Signed certificate |
| `private.key` | Private key (mode 0600) |
| `ca_certificate.crt` | Issuing CA certificate |
| `full_chain.crt` | CA + certificate |
| `certificate.pem` | Certificate + key bundle (mode 0600) |
JSON keys: `certificate`, `private_key`, `ca_certificate`, `full_chain`.
### SSH host certificate signing
```sh
# Plain output (signed cert to stdout)
certmanager ssh \
--public-key "ssh-rsa AAAA..." \
--valid-principals host.example.com,host,10.0.0.1
# JSON output (for use with Puppet generate())
certmanager ssh \
--public-key "$(cat /etc/ssh/ssh_host_rsa_key.pub)" \
--valid-principals host.example.com,host \
--ttl 87600h \
--json
```
JSON key: `signed_key`.
### Global flags
| Flag | Default | Description |
|---|---|---|
| `--config` | `~/.config/certmanager/config.yaml` | Path to config file |
## Development
```sh
make build # compile
make test # run tests
make test-verbose # run tests with -v
make tidy # go mod tidy
make lint # golangci-lint (requires golangci-lint installed)
```
## Release
Uses [goreleaser](https://goreleaser.com/). Tag a version and run:
```sh
goreleaser release --clean
```