Skip to content

Commit

Permalink
feat: domain format (#108)
Browse files Browse the repository at this point in the history
* feat: allow custom domain format in vault path

* feat: explicitly specify domain

* feat: Remove hardcoded path for client

* fix: Fix validation for domainpathformat
  • Loading branch information
soerenschneider authored Jan 29, 2022
1 parent 6813d98 commit 25f0779
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 8 deletions.
7 changes: 1 addition & 6 deletions cmd/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,8 @@ import (
"github.com/soerenschneider/acmevault/internal/client/hooks"
"github.com/soerenschneider/acmevault/internal/config"
"github.com/soerenschneider/acmevault/pkg/certstorage/vault"
"strings"
)

// Prefix of the configured AppRole role_ids for this tool
const roleIdPrefix = "acme-client-"

func main() {
configPath := cmd.ParseCliFlags()
log.Info().Msgf("acmevault-client version %s, commit %s", internal.BuildVersion, internal.CommitHash)
Expand Down Expand Up @@ -65,8 +61,7 @@ func pickUpCerts(client *client.VaultAcmeClient, conf config.AcmeVaultClientConf
return errors.New("empty client passed")
}

domain := strings.ReplaceAll(conf.RoleId, roleIdPrefix, "")
return client.RetrieveAndSave(domain)
return client.RetrieveAndSave(conf.Domain)
}

func writeMetrics(conf config.AcmeVaultClientConfig) {
Expand Down
7 changes: 7 additions & 0 deletions internal/config/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package config

import (
"encoding/json"
"errors"
"fmt"
"github.com/rs/zerolog/log"
"io/ioutil"
Expand All @@ -10,6 +11,7 @@ import (
type AcmeVaultClientConfig struct {
VaultConfig
FsWriterConfig
Domain string `json:"domain"`
Hook []string `json:"hooks"`
MetricsPath string `json:"metricsPath"`
}
Expand All @@ -27,6 +29,10 @@ func AcmeVaultClientConfigFromFile(path string) (AcmeVaultClientConfig, error) {
}

func (conf AcmeVaultClientConfig) Validate() error {
if len(conf.Domain) == 0 {
return errors.New("Missing field `domain`")
}

err := conf.FsWriterConfig.Validate()
if err != nil {
return err
Expand All @@ -39,6 +45,7 @@ func (conf AcmeVaultClientConfig) Print() {
log.Info().Msg("--- Client Config Start ---")
conf.VaultConfig.Print()
conf.FsWriterConfig.Print()
log.Info().Msgf("Domain=%s", conf.Domain)
if len(conf.Hook) > 0 {
log.Info().Msgf("Hooks=%v", conf.Hook)
}
Expand Down
10 changes: 10 additions & 0 deletions internal/config/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type VaultConfig struct {
TokenIncreaseSeconds int `json:"tokenIncreaseSeconds"`
TokenIncreaseInterval int `json:"tokenIncreaseInterval"`
PathPrefix string `json:"vaultPathPrefix"`
DomainPathFormat string `json:"domainPathFormat"`
}

func (conf *VaultConfig) IsTokenIncreaseEnabled() bool {
Expand Down Expand Up @@ -53,6 +54,9 @@ func (conf *VaultConfig) Print() {
if conf.TokenIncreaseInterval > 0 {
log.Info().Msgf("TokenIncreaseInterval=%d", conf.TokenIncreaseInterval)
}
if len(conf.DomainPathFormat) > 0 {
log.Info().Msgf("DomainPathFormat=%s", conf.DomainPathFormat)
}
}

func DefaultVaultConfig() VaultConfig {
Expand Down Expand Up @@ -104,6 +108,12 @@ func (conf *VaultConfig) Validate() error {
return errors.New("specified secretIdFile is not writable, quitting")
}

if len(conf.DomainPathFormat) > 0 {
if !strings.ContainsRune(conf.DomainPathFormat, '%') {
return fmt.Errorf("the domainPathFormat '%s' does not seem to be a valid format string", conf.DomainPathFormat)
}
}

return nil
}

Expand Down
13 changes: 11 additions & 2 deletions pkg/certstorage/vault/vault.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,13 @@ func (vault *VaultBackend) unwrapAndSaveSecretId(wrappingToken, secretIdFile str
return parsed, nil
}

func (vault *VaultBackend) formatDomain(domain string) string {
if len(vault.conf.DomainPathFormat) == 0 {
return domain
}
return fmt.Sprintf(vault.conf.DomainPathFormat, domain)
}

func (vault *VaultBackend) getAwsCredentialsPath() string {
return fmt.Sprintf("/aws/creds/%s", awsRole)
}
Expand All @@ -502,9 +509,11 @@ func (vault *VaultBackend) getAccountPath(hash string) string {
}

func (vault *VaultBackend) getCertDataPath(domain string) string {
return fmt.Sprintf("%s/client/%s/certificate", vault.namespacedPrefix, domain)
domainFormatted := vault.formatDomain(domain)
return fmt.Sprintf("%s/client/%s/certificate", vault.namespacedPrefix, domainFormatted)
}

func (vault *VaultBackend) getSecretDataPath(domain string) string {
return fmt.Sprintf("%s/client/%s/privatekey", vault.namespacedPrefix, domain)
domainFormatted := vault.formatDomain(domain)
return fmt.Sprintf("%s/client/%s/privatekey", vault.namespacedPrefix, domainFormatted)
}
55 changes: 55 additions & 0 deletions pkg/certstorage/vault/vault_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package vault

import (
"github.com/hashicorp/vault/api"
"github.com/soerenschneider/acmevault/internal/config"
"reflect"
"testing"
)
Expand Down Expand Up @@ -45,3 +47,56 @@ func Test_buildSecretPayload(t *testing.T) {
})
}
}

func TestVaultBackend_getSecretDataPath(t *testing.T) {
type fields struct {
client *api.Client
conf config.VaultConfig
revokeToken bool
namespacedPrefix string
}
tests := []struct {
name string
fields fields
args string
want string
}{
{
name: "custom domain path",
fields: fields{
client: nil,
conf: config.VaultConfig{
DomainPathFormat: "machine-%s",
},
revokeToken: false,
namespacedPrefix: "acmevault",
},
args: "test.domain.tld",
want: "acmevault/client/machine-test.domain.tld/privatekey",
},
{
name: "no domain format given",
fields: fields{
client: nil,
conf: config.VaultConfig{},
revokeToken: false,
namespacedPrefix: "acmevault",
},
args: "test.domain.tld",
want: "acmevault/client/test.domain.tld/privatekey",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
vault := &VaultBackend{
client: tt.fields.client,
conf: tt.fields.conf,
revokeToken: tt.fields.revokeToken,
namespacedPrefix: tt.fields.namespacedPrefix,
}
if got := vault.getSecretDataPath(tt.args); got != tt.want {
t.Errorf("getSecretDataPath() = %v, want %v", got, tt.want)
}
})
}
}

0 comments on commit 25f0779

Please sign in to comment.