Merge pull request #3 from gambol99/fix/formatting
- - fixed up the formatting
This commit is contained in:
commit
096e365598
1
Makefile
1
Makefile
|
@ -14,6 +14,7 @@ build:
|
||||||
|
|
||||||
docker: build
|
docker: build
|
||||||
sudo docker build -t ${AUTHOR}/${NAME} .
|
sudo docker build -t ${AUTHOR}/${NAME} .
|
||||||
|
sudo docker build -t ${AUTHOR}/${NAME} .
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf ./build 2>/dev/null
|
rm -rf ./build 2>/dev/null
|
||||||
|
|
|
@ -21,8 +21,9 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
"github.com/golang/glog"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// config ... the command line configuration
|
// config ... the command line configuration
|
||||||
|
@ -57,7 +58,7 @@ func init() {
|
||||||
flag.StringVar(&options.secretsDirectory, "output", getEnv("VAULT_OUTPUT", "/etc/secrets"), "the full path to write the protected resources (VAULT_OUTPUT if available)")
|
flag.StringVar(&options.secretsDirectory, "output", getEnv("VAULT_OUTPUT", "/etc/secrets"), "the full path to write the protected resources (VAULT_OUTPUT if available)")
|
||||||
flag.BoolVar(&options.deleteToken, "delete-token", false, "once the we have connected to vault, delete the token file from disk")
|
flag.BoolVar(&options.deleteToken, "delete-token", false, "once the we have connected to vault, delete the token file from disk")
|
||||||
flag.BoolVar(&options.dryRun, "dry-run", false, "perform a dry run, printing the content to screen")
|
flag.BoolVar(&options.dryRun, "dry-run", false, "perform a dry run, printing the content to screen")
|
||||||
flag.DurationVar(&options.statsInterval, "stats", time.Duration(5) * time.Minute, "the interval to produce statistics on the accessed resources")
|
flag.DurationVar(&options.statsInterval, "stats", time.Duration(5)*time.Minute, "the interval to produce statistics on the accessed resources")
|
||||||
flag.Var(options.resources, "cn", "a resource to retrieve and monitor from vault (e.g. pki:name:cert.name, secret:db_password, aws:s3_backup)")
|
flag.Var(options.resources, "cn", "a resource to retrieve and monitor from vault (e.g. pki:name:cert.name, secret:db_password, aws:s3_backup)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
4
main.go
4
main.go
|
@ -102,7 +102,7 @@ func processResource(rn *vaultResource, data map[string]interface{}) error {
|
||||||
case "cert":
|
case "cert":
|
||||||
files := map[string]string{
|
files := map[string]string{
|
||||||
"certificate": "crt",
|
"certificate": "crt",
|
||||||
"issuing_ca": "ca",
|
"issuing_ca": "ca",
|
||||||
"private_key": "key",
|
"private_key": "key",
|
||||||
}
|
}
|
||||||
for key, suffix := range files {
|
for key, suffix := range files {
|
||||||
|
@ -169,4 +169,4 @@ func writeFile(filename string, content []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
18
utils.go
18
utils.go
|
@ -17,11 +17,11 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -30,10 +30,10 @@ func init() {
|
||||||
|
|
||||||
// showUsage ... prints the command usage and exits
|
// showUsage ... prints the command usage and exits
|
||||||
// message : an error message to display if exiting with an error
|
// message : an error message to display if exiting with an error
|
||||||
func showUsage(message string, args ... interface{}) {
|
func showUsage(message string, args ...interface{}) {
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
if message != "" {
|
if message != "" {
|
||||||
fmt.Printf("\n[error] " + message + "\n", args...)
|
fmt.Printf("\n[error] "+message+"\n", args...)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,14 +41,14 @@ func showUsage(message string, args ... interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// randomWait ... wait for a random amout of time
|
// randomWait ... wait for a random amout of time
|
||||||
func randomWait(min, max int ) <-chan time.Time {
|
func randomWait(min, max int) <-chan time.Time {
|
||||||
return time.After(time.Duration(getRandomWithin(min,max)) * time.Second)
|
return time.After(time.Duration(getRandomWithin(min, max)) * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getKeys ... retrieve a list of keys from the map
|
// getKeys ... retrieve a list of keys from the map
|
||||||
func getKeys(data map[string]interface{}) []string {
|
func getKeys(data map[string]interface{}) []string {
|
||||||
var list []string
|
var list []string
|
||||||
for key, _ := range data {
|
for key := range data {
|
||||||
list = append(list, key)
|
list = append(list, key)
|
||||||
}
|
}
|
||||||
return list
|
return list
|
||||||
|
@ -58,7 +58,7 @@ func getKeys(data map[string]interface{}) []string {
|
||||||
// min : the smallest number we can accept
|
// min : the smallest number we can accept
|
||||||
// max : the largest number we can accept
|
// max : the largest number we can accept
|
||||||
func getRandomWithin(min, max int) int {
|
func getRandomWithin(min, max int) int {
|
||||||
return rand.Intn(max - min) + min
|
return rand.Intn(max-min) + min
|
||||||
}
|
}
|
||||||
|
|
||||||
// getEnv ... checks to see if an environment variable exists otherwise uses the default
|
// getEnv ... checks to see if an environment variable exists otherwise uses the default
|
||||||
|
|
31
vault.go
31
vault.go
|
@ -17,11 +17,11 @@ limitations under the License.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"fmt"
|
"github.com/hashicorp/vault/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
// a channel to send resource
|
// a channel to send resource
|
||||||
|
@ -75,13 +75,13 @@ func (r *watchedResource) notifyOnRenewal(ch chan *watchedResource) {
|
||||||
if r.renewalTime <= 0 {
|
if r.renewalTime <= 0 {
|
||||||
glog.V(10).Infof("calculating the renewal between 80-95 pcent of lease time: %d seconds", r.secret.LeaseDuration)
|
glog.V(10).Infof("calculating the renewal between 80-95 pcent of lease time: %d seconds", r.secret.LeaseDuration)
|
||||||
r.renewalTime = time.Duration(getRandomWithin(
|
r.renewalTime = time.Duration(getRandomWithin(
|
||||||
int(float64(r.secret.LeaseDuration) * 0.8),
|
int(float64(r.secret.LeaseDuration)*0.8),
|
||||||
int(float64(r.secret.LeaseDuration) * 0.95))) * time.Second
|
int(float64(r.secret.LeaseDuration)*0.95))) * time.Second
|
||||||
}
|
}
|
||||||
|
|
||||||
glog.V(3).Infof("setting a renewal notification on resource: %s, time: %s", r.resource, r.renewalTime)
|
glog.V(3).Infof("setting a renewal notification on resource: %s, time: %s", r.resource, r.renewalTime)
|
||||||
// step: wait for the duration
|
// step: wait for the duration
|
||||||
<- time.After(r.renewalTime)
|
<-time.After(r.renewalTime)
|
||||||
// step: send the notification on the renewal channel
|
// step: send the notification on the renewal channel
|
||||||
ch <- r
|
ch <- r
|
||||||
}()
|
}()
|
||||||
|
@ -122,9 +122,10 @@ func newVaultService(url, token string) (*vaultService, error) {
|
||||||
func (r vaultService) vaultServiceProcessor() {
|
func (r vaultService) vaultServiceProcessor() {
|
||||||
go func() {
|
go func() {
|
||||||
// a list of resource being watched
|
// a list of resource being watched
|
||||||
items := make([]*watchedResource, 0)
|
var items []*watchedResource
|
||||||
|
|
||||||
// the channel to receive renewal notifications on
|
// the channel to receive renewal notifications on
|
||||||
renewChannel:= make(chan *watchedResource, 10)
|
renewChannel := make(chan *watchedResource, 10)
|
||||||
retrieveChannel := make(chan *watchedResource, 10)
|
retrieveChannel := make(chan *watchedResource, 10)
|
||||||
revokeChannel := make(chan string, 10)
|
revokeChannel := make(chan string, 10)
|
||||||
statsChannel := time.NewTicker(options.statsInterval)
|
statsChannel := time.NewTicker(options.statsInterval)
|
||||||
|
@ -142,12 +143,12 @@ func (r vaultService) vaultServiceProcessor() {
|
||||||
// step: push into the retrieval channel
|
// step: push into the retrieval channel
|
||||||
retrieveChannel <- x
|
retrieveChannel <- x
|
||||||
|
|
||||||
case x := <- retrieveChannel:
|
case x := <-retrieveChannel:
|
||||||
// step: save the current lease if we have one
|
// step: save the current lease if we have one
|
||||||
leaseId := ""
|
leaseID := ""
|
||||||
if x.secret != nil && x.secret.LeaseID != "" {
|
if x.secret != nil && x.secret.LeaseID != "" {
|
||||||
leaseId = x.secret.LeaseID
|
leaseID = x.secret.LeaseID
|
||||||
glog.V(10).Infof("resource: %s has a previous lease: %s", x.resource, leaseId)
|
glog.V(10).Infof("resource: %s has a previous lease: %s", x.resource, leaseID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// step: retrieve the resource from vault
|
// step: retrieve the resource from vault
|
||||||
|
@ -163,8 +164,8 @@ func (r vaultService) vaultServiceProcessor() {
|
||||||
glog.Infof("succesfully retrieved resournce: %s, leaseID: %s", x.resource, x.secret.LeaseID)
|
glog.Infof("succesfully retrieved resournce: %s, leaseID: %s", x.resource, x.secret.LeaseID)
|
||||||
|
|
||||||
// step: if we had a previous lease and the option is to revoke, lets throw into the revoke channel
|
// step: if we had a previous lease and the option is to revoke, lets throw into the revoke channel
|
||||||
if leaseId != "" && x.resource.revoked {
|
if leaseID != "" && x.resource.revoked {
|
||||||
revokeChannel <- leaseId
|
revokeChannel <- leaseID
|
||||||
}
|
}
|
||||||
|
|
||||||
// step: setup a timer for renewal
|
// step: setup a timer for renewal
|
||||||
|
@ -255,7 +256,7 @@ func (r vaultService) upstream(item *watchedResource, s *api.Secret) {
|
||||||
glog.V(6).Infof("sending the event for resource: %s upstream to listener: %v", item.resource, item.listener)
|
glog.V(6).Infof("sending the event for resource: %s upstream to listener: %v", item.resource, item.listener)
|
||||||
item.listener <- vaultResourceEvent{
|
item.listener <- vaultResourceEvent{
|
||||||
resource: item.resource,
|
resource: item.resource,
|
||||||
secret: s.Data,
|
secret: s.Data,
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -336,7 +337,7 @@ func (r vaultService) get(rn *watchedResource) (err error) {
|
||||||
rn.leaseExpireTime = rn.lastUpdated.Add(time.Duration(secret.LeaseDuration))
|
rn.leaseExpireTime = rn.lastUpdated.Add(time.Duration(secret.LeaseDuration))
|
||||||
|
|
||||||
glog.V(3).Infof("retrieved resource: %s, leaseId: %s, lease_time: %s",
|
glog.V(3).Infof("retrieved resource: %s, leaseId: %s, lease_time: %s",
|
||||||
rn.resource, rn.secret.LeaseID, time.Duration(rn.secret.LeaseDuration) * time.Second)
|
rn.resource, rn.secret.LeaseID, time.Duration(rn.secret.LeaseDuration)*time.Second)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,28 +19,25 @@ package main
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
"time"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"github.com/golang/glog"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// OptionFilename ... option to set the filename of the resource
|
// OptionFilename ... option to set the filename of the resource
|
||||||
OptionFilename = "fn"
|
OptionFilename = "fn"
|
||||||
// OptionsFormat ... option to set the output format (yaml, xml, json)
|
// OptionFormat ... option to set the output format (yaml, xml, json)
|
||||||
OptionFormat = "fmt"
|
OptionFormat = "fmt"
|
||||||
// OptionsCommonName ... use by the PKI resource
|
// OptionCommonName ... use by the PKI resource
|
||||||
OptionCommonName = "cn"
|
OptionCommonName = "cn"
|
||||||
// OptionTemplatePath ... the full path to a template
|
// OptionTemplatePath ... the full path to a template
|
||||||
OptionsTemplatePath = "tpl"
|
OptionTemplatePath = "tpl"
|
||||||
// OptionRenew ... a duration to renew the resource
|
// OptionRenewal ... a duration to renew the resource
|
||||||
OptionRenewal = "rn"
|
OptionRenewal = "rn"
|
||||||
// OptionRevoke ... revoke an old lease when retrieving a new one
|
// OptionRevoke ... revoke an old lease when retrieving a new one
|
||||||
OptionRevoke = "rv"
|
OptionRevoke = "rv"
|
||||||
// OptionUpdate ... override the lease of the resource
|
// OptionUpdate ... override the lease of the resource
|
||||||
OptionUpdate = "up"
|
OptionUpdate = "up"
|
||||||
|
|
||||||
DefaultRenewable = "false"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -48,20 +45,22 @@ var (
|
||||||
|
|
||||||
// a map of valid resource to retrieve from vault
|
// a map of valid resource to retrieve from vault
|
||||||
validResources = map[string]bool{
|
validResources = map[string]bool{
|
||||||
"pki": true,
|
"pki": true,
|
||||||
"aws": true,
|
"aws": true,
|
||||||
"secret": true,
|
"secret": true,
|
||||||
"mysql": true,
|
"mysql": true,
|
||||||
"tpl": true,
|
"tpl": true,
|
||||||
|
"postgres": true,
|
||||||
|
"cassandra": true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func defaultVaultResource() *vaultResource {
|
func defaultVaultResource() *vaultResource {
|
||||||
return &vaultResource{
|
return &vaultResource{
|
||||||
format: "yaml",
|
format: "yaml",
|
||||||
renewable: false,
|
renewable: false,
|
||||||
revoked: false,
|
revoked: false,
|
||||||
options: make(map[string]string, 0),
|
options: make(map[string]string, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +110,7 @@ func (r *vaultResource) isValidResource() error {
|
||||||
return fmt.Errorf("pki resource requires a common name specified")
|
return fmt.Errorf("pki resource requires a common name specified")
|
||||||
}
|
}
|
||||||
case "tpl":
|
case "tpl":
|
||||||
if _, found := r.options[OptionsTemplatePath]; !found {
|
if _, found := r.options[OptionTemplatePath]; !found {
|
||||||
return fmt.Errorf("template resource requires a template path option")
|
return fmt.Errorf("template resource requires a template path option")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,34 +127,30 @@ func (r *vaultResource) isValidOptions() error {
|
||||||
if matched := resourceFormatRegex.MatchString(r.options[OptionFormat]); !matched {
|
if matched := resourceFormatRegex.MatchString(r.options[OptionFormat]); !matched {
|
||||||
return fmt.Errorf("unsupported output format: %s", r.options[OptionFormat])
|
return fmt.Errorf("unsupported output format: %s", r.options[OptionFormat])
|
||||||
}
|
}
|
||||||
glog.V(20).Infof("setting the format: %s on resource: %s", val, r)
|
|
||||||
r.format = val
|
r.format = val
|
||||||
case OptionUpdate:
|
case OptionUpdate:
|
||||||
duration, err := time.ParseDuration(val)
|
duration, err := time.ParseDuration(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("the update option: %s is not value, should be a duration format", val)
|
return fmt.Errorf("the update option: %s is not value, should be a duration format", val)
|
||||||
}
|
}
|
||||||
glog.V(20).Infof("setting the update time: %s on resource: %s", duration, r)
|
|
||||||
r.update = duration
|
r.update = duration
|
||||||
case OptionRevoke:
|
case OptionRevoke:
|
||||||
choice, err := strconv.ParseBool(val)
|
choice, err := strconv.ParseBool(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("the revoke option: %s is invalid, should be a boolean", val)
|
return fmt.Errorf("the revoke option: %s is invalid, should be a boolean", val)
|
||||||
}
|
}
|
||||||
glog.V(20).Infof("setting the revoked: %t on resource: %s", choice, r)
|
|
||||||
r.revoked = choice
|
r.revoked = choice
|
||||||
case OptionRenewal:
|
case OptionRenewal:
|
||||||
choice, err := strconv.ParseBool(val)
|
choice, err := strconv.ParseBool(val)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("the renewal option: %s is invalid, should be a boolean", val)
|
return fmt.Errorf("the renewal option: %s is invalid, should be a boolean", val)
|
||||||
}
|
}
|
||||||
glog.V(20).Infof("setting the renewable: %t on resource: %s", choice, r)
|
|
||||||
r.renewable = choice
|
r.renewable = choice
|
||||||
case OptionFilename:
|
case OptionFilename:
|
||||||
// @TODO need to check it's valid filename / path
|
// @TODO need to check it's valid filename / path
|
||||||
case OptionCommonName:
|
case OptionCommonName:
|
||||||
// @TODO need to check it's a valid hostname
|
// @TODO need to check it's a valid hostname
|
||||||
case OptionsTemplatePath:
|
case OptionTemplatePath:
|
||||||
if exists, _ := fileExists(val); !exists {
|
if exists, _ := fileExists(val); !exists {
|
||||||
return fmt.Errorf("the template file: %s does not exist", val)
|
return fmt.Errorf("the template file: %s does not exist", val)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ func TestResourceFilename(t *testing.T) {
|
||||||
assert.Equal(t, "credentials", rn.filename())
|
assert.Equal(t, "credentials", rn.filename())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestIsValid(t *testing.T) {
|
func TestIsValid(t *testing.T) {
|
||||||
resource := defaultVaultResource()
|
resource := defaultVaultResource()
|
||||||
resource.name = "/test/name"
|
resource.name = "/test/name"
|
||||||
|
|
|
@ -33,10 +33,6 @@ type vaultResources struct {
|
||||||
items []*vaultResource
|
items []*vaultResource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r vaultResources) size() int {
|
|
||||||
return len(r.items)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set ... implementation for the parser
|
// Set ... implementation for the parser
|
||||||
func (r *vaultResources) Set(value string) error {
|
func (r *vaultResources) Set(value string) error {
|
||||||
rn := defaultVaultResource()
|
rn := defaultVaultResource()
|
||||||
|
|
|
@ -22,7 +22,6 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func TestSetResources(t *testing.T) {
|
func TestSetResources(t *testing.T) {
|
||||||
var items vaultResources
|
var items vaultResources
|
||||||
|
|
||||||
|
@ -41,13 +40,6 @@ func TestSetResources(t *testing.T) {
|
||||||
assert.NotNil(t, items.Set("fn=filename.test,fmt=yaml"))
|
assert.NotNil(t, items.Set("fn=filename.test,fmt=yaml"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestResourceSize(t *testing.T) {
|
|
||||||
var items vaultResources
|
|
||||||
items.Set("secret:test:fn=filename.test,fmt=yaml")
|
|
||||||
items.Set("secret:test:fn=fileame.test")
|
|
||||||
assert.Equal(t, 2, items.size())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestResources(t *testing.T) {
|
func TestResources(t *testing.T) {
|
||||||
var items vaultResources
|
var items vaultResources
|
||||||
items.Set("secret:test:fn=filename.test,fmt=yaml")
|
items.Set("secret:test:fn=filename.test,fmt=yaml")
|
||||||
|
|
|
@ -15,4 +15,3 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
|
|
@ -19,4 +19,4 @@ package main
|
||||||
const (
|
const (
|
||||||
Version = "0.0.1"
|
Version = "0.0.1"
|
||||||
GitSha = ""
|
GitSha = ""
|
||||||
)
|
)
|
||||||
|
|
Reference in a new issue