Skip to content

Commit

Permalink
Add vault audit configuration
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Winther <jippignu@gmail.com>
  • Loading branch information
jippi committed Sep 9, 2019
1 parent 6293434 commit dc4368f
Show file tree
Hide file tree
Showing 6 changed files with 207 additions and 1 deletion.
65 changes: 65 additions & 0 deletions command/vault/audit_push.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package vault

import (
"fmt"

"github.com/hashicorp/vault/api"
"github.com/seatgeek/hashi-helper/config"
log "github.com/sirupsen/logrus"
cli "gopkg.in/urfave/cli.v1"
)

// AuditPush ...
func AuditPush(c *cli.Context) error {
config, err := config.NewConfigFromCLI(c)
if err != nil {
return err
}

return AuditPushWithConfig(c, config)
}

// AuditPushWithConfig ...
func AuditPushWithConfig(c *cli.Context, config *config.Config) error {
env := c.GlobalString("environment")
if env == "" {
return fmt.Errorf("Pushing auth backends require a 'environment' value (--environment or ENV[ENVIRONMENT])")
}

if !config.Environments.Contains(env) {
return fmt.Errorf("Could not find any environment with name %s in configuration", env)
}

client, err := api.NewClient(nil)
if err != nil {
return err
}

audits, err := client.Sys().ListAudit()
if err != nil {
return err
}

for _, audit := range config.VaultAudits {
log.Printf(" Writing audit path: %s", audit.Path)

path := fmt.Sprintf("/sys/audit/%s", audit.Path)
if _, ok := audits[audit.Path+"/"]; ok {
s, err := client.Logical().Delete(path)
if err != nil {
log.Fatal(err)
}

printRemoteSecretWarnings(s)
}

s, err := client.Logical().Write(path, audit.ToMap())
if err != nil {
log.Fatal(err)
}

printRemoteSecretWarnings(s)
}

return nil
}
4 changes: 4 additions & 0 deletions command/vault/push_all.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ func PushAll(cli *cli.Context) error {

// PushAllWithConfig ...
func PushAllWithConfig(cli *cli.Context, config *cfg.Config) error {
if err := AuditPushWithConfig(cli, config); err != nil {
return err
}

if err := AuthPushWithConfig(cli, config); err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Config struct {
VaultMounts VaultMounts
VaultPolicies VaultPolicies
VaultSecrets VaultSecrets
VaultAudits VaultAudits
}

// NewConfigFromCLI will take a CLI context and create config from it
Expand Down
7 changes: 6 additions & 1 deletion config/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,13 +121,18 @@ func (c *Config) processEnvironments(list *ast.ObjectList) error {

// check for valid keys inside an environment stanza
x := envAST.Val.(*ast.ObjectType).List
valid := []string{"application", "auth", "policy", "mount", "secret", "secrets", "service", "kv"}
valid := []string{"application", "auth", "audit", "policy", "mount", "secret", "secrets", "service", "kv"}
if err := c.checkHCLKeys(x, valid); err != nil {
return err
}

env := c.Environments.getOrSet(&Environment{Name: envName})

c.logger.Debug("Scanning for audit{}")
if err := c.parseVaultAuditStanza(x.Filter("audit"), env); err != nil {
return err
}

c.logger.Debug("Scanning for application{}")
if err := c.parseApplicationStanza(x.Filter("application"), env); err != nil {
return err
Expand Down
124 changes: 124 additions & 0 deletions config/vault_audit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package config

import (
"fmt"

"github.com/hashicorp/hcl"
"github.com/hashicorp/hcl/hcl/ast"
)

// Secret ...
type Audit struct {
Description string `hcl:"description"`
Environment *Environment
Key string
Local bool `hcl:"local"`
Options map[string]interface{} `hcl:"options"`
Path string `hcl:"path"`
Type string `hcl:"type"`
}

// Equal ...
func (s *Audit) Equal(o *Audit) bool {
return s.Path == o.Path && s.Key == o.Key
}

func (s *Audit) ToMap() map[string]interface{} {
return map[string]interface{}{
"description": s.Description,
"options": s.Options,
"type": s.Type,
"local": s.Local,
}
}

// VaultAudits struct
//
// environment -> application
type VaultAudits []*Audit

// Add ...
func (e *VaultAudits) Add(audit *Audit) bool {
if !e.Exists(audit) {
*e = append(*e, audit)
return true
}

return false
}

// Exists ...
func (e *VaultAudits) Exists(audit *Audit) bool {
for _, existing := range *e {
if audit.Equal(existing) {
return true
}
}

return false
}

// Get ...
func (e *VaultAudits) Get(audit *Audit) *Audit {
for _, existing := range *e {
if audit.Equal(existing) {
return existing
}
}

return nil
}

// GetOrSet ...
func (e *VaultAudits) GetOrSet(audit *Audit) *Audit {
existing := e.Get(audit)
if existing != nil {
return existing
}

e.Add(audit)
return audit
}

func (e *VaultAudits) List() []string {
res := []string{}

for _, sec := range *e {
res = append(res, sec.Path)
}

return res
}

// parseVaultAuditStanza
// parse out `environment -> audit
func (c *Config) parseVaultAuditStanza(list *ast.ObjectList, env *Environment) error {
if len(list.Items) == 0 {
return nil
}

c.logger = c.logger.WithField("stanza", "audit")
c.logger.Debugf("Found %d audit{}", len(list.Items))
for _, auditData := range list.Items {
if len(auditData.Keys) != 1 {
return fmt.Errorf("Missing audit name in line %+v", auditData.Keys[0].Pos())
}

var audit Audit
if err := hcl.DecodeObject(&audit, auditData); err != nil {
return err
}

auditName := auditData.Keys[0].Token.Value().(string)

audit.Key = auditName
audit.Path = auditName
audit.Environment = env

if c.VaultAudits.Add(&audit) == false {
c.logger.Warnf("Ignored duplicate audit '%s' -> '%s' in line %s", audit.Environment.Name, audit.Key, auditData.Keys[0].Token.Pos)
}
}

return nil
}
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ func main() {
return vaultCommand.PoliciesPush(c)
},
},
{
Name: "vault-push-audit",
Usage: "Write audit configuration to remote Vault instance",
Action: func(c *cli.Context) error {
return vaultCommand.AuditPush(c)
},
},
{
Name: "vault-push-mounts",
Usage: "Write vault mounts to remote Vault instance",
Expand Down

0 comments on commit dc4368f

Please sign in to comment.