Use common funcs / fix panic / clarify docs
This commit is contained in:
parent
8666ebceca
commit
78c280b1b7
|
@ -1,8 +1,14 @@
|
|||
package template
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
vaultapi "github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
// DeprecatedTemplateFunc wraps a template func to warn users that it's
|
||||
|
@ -17,3 +23,41 @@ func DeprecatedTemplateFunc(funcName, useInstead string, deprecated func(string)
|
|||
return deprecated(in)
|
||||
}
|
||||
}
|
||||
|
||||
// Vault retrieves a secret from an HC vault KV store
|
||||
func Vault(path string, key string) (string, error) {
|
||||
|
||||
if token := os.Getenv("VAULT_TOKEN"); token == "" {
|
||||
return "", errors.New("Must set VAULT_TOKEN env var in order to use vault template function")
|
||||
}
|
||||
|
||||
vaultConfig := vaultapi.DefaultConfig()
|
||||
cli, err := vaultapi.NewClient(vaultConfig)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error getting Vault client: %s", err)
|
||||
}
|
||||
secret, err := cli.Logical().Read(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error reading vault secret: %s", err)
|
||||
}
|
||||
if secret == nil {
|
||||
return "", errors.New("Vault Secret does not exist at the given path")
|
||||
}
|
||||
|
||||
data, ok := secret.Data["data"]
|
||||
if !ok {
|
||||
// maybe ths is v1, not v2 kv store
|
||||
value, ok := secret.Data[key]
|
||||
if ok {
|
||||
return value.(string), nil
|
||||
}
|
||||
|
||||
// neither v1 nor v2 proudced a valid value
|
||||
return "", fmt.Errorf("Vault data was empty at the given path. Warnings: %s", strings.Join(secret.Warnings, "; "))
|
||||
}
|
||||
|
||||
if val, ok := data.(map[string]interface{})[key]; ok {
|
||||
return val.(string), nil
|
||||
}
|
||||
return "", errors.New("Vault path does not contain the requested key")
|
||||
}
|
||||
|
|
|
@ -1,15 +1,10 @@
|
|||
package function
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/function"
|
||||
|
||||
vaultapi "github.com/hashicorp/vault/api"
|
||||
commontpl "github.com/hashicorp/packer/common/template"
|
||||
)
|
||||
|
||||
// VaultFunc constructs a function that retrieves KV secrets from HC vault
|
||||
|
@ -26,47 +21,11 @@ var VaultFunc = function.New(&function.Spec{
|
|||
},
|
||||
Type: function.StaticReturnType(cty.String),
|
||||
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
|
||||
|
||||
path := args[0].AsString()
|
||||
key := args[1].AsString()
|
||||
|
||||
if token := os.Getenv("VAULT_TOKEN"); token == "" {
|
||||
return cty.StringVal(""), errors.New("Must set VAULT_TOKEN env var in order to " +
|
||||
"use vault template function")
|
||||
}
|
||||
val, err := commontpl.Vault(path, key)
|
||||
|
||||
vaultConfig := vaultapi.DefaultConfig()
|
||||
cli, err := vaultapi.NewClient(vaultConfig)
|
||||
if err != nil {
|
||||
return cty.StringVal(""), fmt.Errorf("Error getting Vault client: %s", err)
|
||||
}
|
||||
secret, err := cli.Logical().Read(path)
|
||||
if err != nil {
|
||||
return cty.StringVal(""), fmt.Errorf("Error reading vault secret: %s", err)
|
||||
}
|
||||
if secret == nil {
|
||||
return cty.StringVal(""), errors.New("Vault Secret does not exist at the given path")
|
||||
}
|
||||
|
||||
data, ok := secret.Data["data"]
|
||||
if !ok {
|
||||
// maybe ths is v1, not v2 kv store
|
||||
value, ok := secret.Data[key]
|
||||
if ok {
|
||||
return cty.StringVal(value.(string)), nil
|
||||
}
|
||||
|
||||
// neither v1 nor v2 proudced a valid value
|
||||
return cty.StringVal(""), fmt.Errorf("Vault data was empty at the "+
|
||||
"given path. Warnings: %s", strings.Join(secret.Warnings, "; "))
|
||||
}
|
||||
|
||||
value := data.(map[string]interface{})[key].(string)
|
||||
return cty.StringVal(value), nil
|
||||
return cty.StringVal(val), err
|
||||
},
|
||||
})
|
||||
|
||||
// Vault returns a secret from a KV store in HC vault
|
||||
func Vault() (cty.Value, error) {
|
||||
return VaultFunc.Call([]cty.Value{})
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@ import (
|
|||
"time"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
commontpl "github.com/hashicorp/packer/common/template"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/common"
|
||||
awssmapi "github.com/hashicorp/packer/template/interpolate/aws/secretsmanager"
|
||||
"github.com/hashicorp/packer/version"
|
||||
vaultapi "github.com/hashicorp/vault/api"
|
||||
strftime "github.com/jehiah/go-strftime"
|
||||
)
|
||||
|
||||
|
@ -289,40 +289,8 @@ func funcGenVault(ctx *Context) interface{} {
|
|||
// semantic checks should catch this.
|
||||
return "", errors.New("Vault vars are only allowed in the variables section")
|
||||
}
|
||||
if token := os.Getenv("VAULT_TOKEN"); token == "" {
|
||||
return "", errors.New("Must set VAULT_TOKEN env var in order to " +
|
||||
"use vault template function")
|
||||
}
|
||||
// const EnvVaultAddress = "VAULT_ADDR"
|
||||
// const EnvVaultToken = "VAULT_TOKEN"
|
||||
vaultConfig := vaultapi.DefaultConfig()
|
||||
cli, err := vaultapi.NewClient(vaultConfig)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error getting Vault client: %s", err)
|
||||
}
|
||||
secret, err := cli.Logical().Read(path)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error reading vault secret: %s", err)
|
||||
}
|
||||
if secret == nil {
|
||||
return "", errors.New("Vault Secret does not exist at the given path")
|
||||
}
|
||||
|
||||
data, ok := secret.Data["data"]
|
||||
if !ok {
|
||||
// maybe ths is v1, not v2 kv store
|
||||
value, ok := secret.Data[key]
|
||||
if ok {
|
||||
return value.(string), nil
|
||||
}
|
||||
|
||||
// neither v1 nor v2 proudced a valid value
|
||||
return "", fmt.Errorf("Vault data was empty at the "+
|
||||
"given path. Warnings: %s", strings.Join(secret.Warnings, "; "))
|
||||
}
|
||||
|
||||
value := data.(map[string]interface{})[key].(string)
|
||||
return value, nil
|
||||
return commontpl.Vault(path, key)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,10 +18,12 @@ If you store a value in vault using `vault kv put secret/hello foo=world`, you
|
|||
can access it using the following:
|
||||
|
||||
```hcl
|
||||
vault("/secret/data/hello" "foo")
|
||||
locals {
|
||||
foo = vault("/secret/data/hello" "foo")
|
||||
}
|
||||
```
|
||||
|
||||
which will assign "my_secret": "world"
|
||||
which will assign `local.foo` with the value "world"
|
||||
|
||||
An example of using a v1 kv engine:
|
||||
|
||||
|
@ -33,15 +35,20 @@ If you store a value in vault using:
|
|||
You can access it using the following:
|
||||
|
||||
```hcl
|
||||
vault("secrets/hello", "foo")
|
||||
locals {
|
||||
foo = vault("secrets/hello", "foo")
|
||||
}
|
||||
```
|
||||
|
||||
This example accesses the Vault path `secret/data/foo` and returns the value
|
||||
stored at the key `bar`, storing it as "my_secret".
|
||||
This example accesses the Vault path `secret/foo` and returns the value
|
||||
stored at the key `foo`, storing it as the local variable `local.foo`.
|
||||
|
||||
In order for this to work, you must set the environment variables `VAULT_TOKEN`
|
||||
and `VAULT_ADDR` to valid values.
|
||||
|
||||
-> **NOTE:** HCL functions can be used in local variable definitions or inline
|
||||
with a provisioner/post-processor. They cannot be used in global variable definitions.
|
||||
|
||||
The api tool we use allows for more custom configuration of the Vault client via
|
||||
environment variables.
|
||||
|
||||
|
|
Loading…
Reference in New Issue