Merge pull request #2653 from evertrue/evertrue/eherot/add_data_bag_secret_to_chef_client
Chef-client provisioner: Add encrypted data bag secret path (Fixes #1945)
This commit is contained in:
commit
3eabc6253d
|
@ -22,23 +22,24 @@ import (
|
|||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
|
||||
ChefEnvironment string `mapstructure:"chef_environment"`
|
||||
SslVerifyMode string `mapstructure:"ssl_verify_mode"`
|
||||
ConfigTemplate string `mapstructure:"config_template"`
|
||||
ExecuteCommand string `mapstructure:"execute_command"`
|
||||
InstallCommand string `mapstructure:"install_command"`
|
||||
Json map[string]interface{}
|
||||
NodeName string `mapstructure:"node_name"`
|
||||
PreventSudo bool `mapstructure:"prevent_sudo"`
|
||||
RunList []string `mapstructure:"run_list"`
|
||||
ServerUrl string `mapstructure:"server_url"`
|
||||
SkipCleanClient bool `mapstructure:"skip_clean_client"`
|
||||
SkipCleanNode bool `mapstructure:"skip_clean_node"`
|
||||
SkipInstall bool `mapstructure:"skip_install"`
|
||||
StagingDir string `mapstructure:"staging_directory"`
|
||||
ClientKey string `mapstructure:"client_key"`
|
||||
ValidationKeyPath string `mapstructure:"validation_key_path"`
|
||||
ValidationClientName string `mapstructure:"validation_client_name"`
|
||||
ChefEnvironment string `mapstructure:"chef_environment"`
|
||||
EncryptedDataBagSecretPath string `mapstructure:"encrypted_data_bag_secret_path"`
|
||||
SslVerifyMode string `mapstructure:"ssl_verify_mode"`
|
||||
ConfigTemplate string `mapstructure:"config_template"`
|
||||
ExecuteCommand string `mapstructure:"execute_command"`
|
||||
InstallCommand string `mapstructure:"install_command"`
|
||||
Json map[string]interface{}
|
||||
NodeName string `mapstructure:"node_name"`
|
||||
PreventSudo bool `mapstructure:"prevent_sudo"`
|
||||
RunList []string `mapstructure:"run_list"`
|
||||
ServerUrl string `mapstructure:"server_url"`
|
||||
SkipCleanClient bool `mapstructure:"skip_clean_client"`
|
||||
SkipCleanNode bool `mapstructure:"skip_clean_node"`
|
||||
SkipInstall bool `mapstructure:"skip_install"`
|
||||
StagingDir string `mapstructure:"staging_directory"`
|
||||
ClientKey string `mapstructure:"client_key"`
|
||||
ValidationKeyPath string `mapstructure:"validation_key_path"`
|
||||
ValidationClientName string `mapstructure:"validation_client_name"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
@ -48,13 +49,15 @@ type Provisioner struct {
|
|||
}
|
||||
|
||||
type ConfigTemplate struct {
|
||||
NodeName string
|
||||
ServerUrl string
|
||||
ClientKey string
|
||||
ValidationKeyPath string
|
||||
ValidationClientName string
|
||||
ChefEnvironment string
|
||||
SslVerifyMode string
|
||||
NodeName string
|
||||
ServerUrl string
|
||||
ClientKey string
|
||||
ValidationKeyPath string
|
||||
ValidationClientName string
|
||||
EncryptedDataBagSecretPath string
|
||||
ChefEnvironment string
|
||||
SslVerifyMode string
|
||||
HasEncryptedDataBagSecretPath bool
|
||||
}
|
||||
|
||||
type ExecuteTemplate struct {
|
||||
|
@ -118,6 +121,15 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
|||
errs, fmt.Errorf("server_url must be set"))
|
||||
}
|
||||
|
||||
if p.config.EncryptedDataBagSecretPath != "" {
|
||||
pFileInfo, err := os.Stat(p.config.EncryptedDataBagSecretPath)
|
||||
|
||||
if err != nil || pFileInfo.IsDir() {
|
||||
errs = packer.MultiErrorAppend(
|
||||
errs, fmt.Errorf("Bad encrypted data bag secret '%s': %s", p.config.EncryptedDataBagSecretPath, err))
|
||||
}
|
||||
}
|
||||
|
||||
jsonValid := true
|
||||
for k, v := range p.config.Json {
|
||||
p.config.Json[k], err = p.deepJsonFix(k, v)
|
||||
|
@ -175,8 +187,16 @@ func (p *Provisioner) Provision(ui packer.Ui, comm packer.Communicator) error {
|
|||
}
|
||||
}
|
||||
|
||||
encryptedDataBagSecretPath := ""
|
||||
if p.config.EncryptedDataBagSecretPath != "" {
|
||||
encryptedDataBagSecretPath = fmt.Sprintf("%s/encrypted_data_bag_secret", p.config.StagingDir)
|
||||
if err := p.uploadFile(ui, comm, encryptedDataBagSecretPath, p.config.EncryptedDataBagSecretPath); err != nil {
|
||||
return fmt.Errorf("Error uploading encrypted data bag secret: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
configPath, err := p.createConfig(
|
||||
ui, comm, nodeName, serverUrl, p.config.ClientKey, remoteValidationKeyPath, p.config.ValidationClientName, p.config.ChefEnvironment, p.config.SslVerifyMode)
|
||||
ui, comm, nodeName, serverUrl, p.config.ClientKey, remoteValidationKeyPath, p.config.ValidationClientName, encryptedDataBagSecretPath, p.config.ChefEnvironment, p.config.SslVerifyMode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error creating Chef config file: %s", err)
|
||||
}
|
||||
|
@ -236,7 +256,17 @@ func (p *Provisioner) uploadDirectory(ui packer.Ui, comm packer.Communicator, ds
|
|||
return comm.UploadDir(dst, src, nil)
|
||||
}
|
||||
|
||||
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, remoteKeyPath string, validationClientName string, chefEnvironment string, sslVerifyMode string) (string, error) {
|
||||
func (p *Provisioner) uploadFile(ui packer.Ui, comm packer.Communicator, dst string, src string) error {
|
||||
f, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
return comm.Upload(dst, f, nil)
|
||||
}
|
||||
|
||||
func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeName string, serverUrl string, clientKey string, remoteKeyPath string, validationClientName string, encryptedDataBagSecretPath string, chefEnvironment string, sslVerifyMode string) (string, error) {
|
||||
ui.Message("Creating configuration file 'client.rb'")
|
||||
|
||||
// Read the template
|
||||
|
@ -258,13 +288,15 @@ func (p *Provisioner) createConfig(ui packer.Ui, comm packer.Communicator, nodeN
|
|||
|
||||
ctx := p.config.ctx
|
||||
ctx.Data = &ConfigTemplate{
|
||||
NodeName: nodeName,
|
||||
ServerUrl: serverUrl,
|
||||
ClientKey: clientKey,
|
||||
ValidationKeyPath: remoteKeyPath,
|
||||
ValidationClientName: validationClientName,
|
||||
ChefEnvironment: chefEnvironment,
|
||||
SslVerifyMode: sslVerifyMode,
|
||||
NodeName: nodeName,
|
||||
ServerUrl: serverUrl,
|
||||
ClientKey: clientKey,
|
||||
ValidationKeyPath: remoteKeyPath,
|
||||
ValidationClientName: validationClientName,
|
||||
ChefEnvironment: chefEnvironment,
|
||||
SslVerifyMode: sslVerifyMode,
|
||||
EncryptedDataBagSecretPath: encryptedDataBagSecretPath,
|
||||
HasEncryptedDataBagSecretPath: encryptedDataBagSecretPath != "",
|
||||
}
|
||||
configString, err := interpolate.Render(tpl, &ctx)
|
||||
if err != nil {
|
||||
|
@ -587,6 +619,9 @@ log_level :info
|
|||
log_location STDOUT
|
||||
chef_server_url "{{.ServerUrl}}"
|
||||
client_key "{{.ClientKey}}"
|
||||
{{if .HasEncryptedDataBagSecretPath}}
|
||||
encrypted_data_bag_secret "{{.EncryptedDataBagSecretPath}}"
|
||||
{{end}}
|
||||
{{if ne .ValidationClientName ""}}
|
||||
validation_client_name "{{.ValidationClientName}}"
|
||||
{{else}}
|
||||
|
|
|
@ -138,6 +138,49 @@ func TestProvisionerPrepare_serverUrl(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProvisionerPrepare_encryptedDataBagSecretPath(t *testing.T) {
|
||||
var err error
|
||||
var p Provisioner
|
||||
|
||||
// Test no config template
|
||||
config := testConfig()
|
||||
delete(config, "encrypted_data_bag_secret_path")
|
||||
err = p.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test with a file
|
||||
tf, err := ioutil.TempFile("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Remove(tf.Name())
|
||||
|
||||
config = testConfig()
|
||||
config["encrypted_data_bag_secret_path"] = tf.Name()
|
||||
p = Provisioner{}
|
||||
err = p.Prepare(config)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
// Test with a directory
|
||||
td, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.RemoveAll(td)
|
||||
|
||||
config = testConfig()
|
||||
config["encrypted_data_bag_secret_path"] = td
|
||||
p = Provisioner{}
|
||||
err = p.Prepare(config)
|
||||
if err == nil {
|
||||
t.Fatal("should have err")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_createDir(t *testing.T) {
|
||||
p1 := &Provisioner{config: Config{PreventSudo: true}}
|
||||
p2 := &Provisioner{config: Config{PreventSudo: false}}
|
||||
|
|
|
@ -50,6 +50,10 @@ configuration is actually required.
|
|||
should use a custom configuration template. See the dedicated "Chef
|
||||
Configuration" section below for more details.
|
||||
|
||||
- `encrypted_data_bag_secret_path` (string) - The path to the file containing
|
||||
the secret for encrypted data bags. By default, this is empty, so no secret
|
||||
will be available.
|
||||
|
||||
- `execute_command` (string) - The command used to execute Chef. This has
|
||||
various [configuration template
|
||||
variables](/docs/templates/configuration-templates.html) available. See
|
||||
|
@ -136,6 +140,7 @@ This template is a [configuration
|
|||
template](/docs/templates/configuration-templates.html) and has a set of
|
||||
variables available to use:
|
||||
|
||||
- `EncryptedDataBagSecretPath` - The path to the encrypted data bag secret
|
||||
- `NodeName` - The node name set in the configuration.
|
||||
- `ServerUrl` - The URL of the Chef Server set in the configuration.
|
||||
- `ValidationKeyPath` - Path to the validation key, if it is set.
|
||||
|
|
Loading…
Reference in New Issue