diff --git a/builtin/provisioners/chef/linux_provisioner_test.go b/builtin/provisioners/chef/linux_provisioner_test.go index d55b4c31a..b793ace46 100644 --- a/builtin/provisioners/chef/linux_provisioner_test.go +++ b/builtin/provisioners/chef/linux_provisioner_test.go @@ -20,6 +20,7 @@ func TestResourceProvider_linuxInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -37,6 +38,7 @@ func TestResourceProvider_linuxInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -55,6 +57,7 @@ func TestResourceProvider_linuxInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -73,6 +76,7 @@ func TestResourceProvider_linuxInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -92,6 +96,7 @@ func TestResourceProvider_linuxInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -112,6 +117,7 @@ func TestResourceProvider_linuxInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", "version": "11.18.6", }), @@ -158,6 +164,7 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -169,10 +176,11 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - linuxConfDir + "/ohai/hints/ohaihint.json": "OHAI-HINT-FILE", - linuxConfDir + "/client.rb": defaultLinuxClientConf, - linuxConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, + linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + linuxConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + linuxConfDir + "/ohai/hints/ohaihint.json": "OHAI-HINT-FILE", + linuxConfDir + "/client.rb": defaultLinuxClientConf, + linuxConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, }, }, @@ -184,6 +192,7 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -191,9 +200,10 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - linuxConfDir + "/client.rb": defaultLinuxClientConf, - linuxConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, + linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + linuxConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + linuxConfDir + "/client.rb": defaultLinuxClientConf, + linuxConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, }, }, @@ -208,6 +218,7 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -215,9 +226,10 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - linuxConfDir + "/client.rb": proxyLinuxClientConf, - linuxConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, + linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + linuxConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + linuxConfDir + "/client.rb": proxyLinuxClientConf, + linuxConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, }, }, @@ -250,6 +262,7 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -257,8 +270,9 @@ func TestResourceProvider_linuxCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - linuxConfDir + "/client.rb": defaultLinuxClientConf, + linuxConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + linuxConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + linuxConfDir + "/client.rb": defaultLinuxClientConf, linuxConfDir + "/first-boot.json": `{"key1":{"subkey1":{"subkey2a":["val1","val2","val3"],` + `"subkey2b":{"subkey3":"value3"}}},"key2":"value2","run_list":["cookbook::recipe"]}`, }, diff --git a/builtin/provisioners/chef/resource_provisioner.go b/builtin/provisioners/chef/resource_provisioner.go index 3e3cb8abc..94b8be67f 100644 --- a/builtin/provisioners/chef/resource_provisioner.go +++ b/builtin/provisioners/chef/resource_provisioner.go @@ -28,6 +28,7 @@ const ( firstBoot = "first-boot.json" logfileDir = "logfiles" linuxConfDir = "/etc/chef" + secretKey = "encrypted_data_bag_secret" validationKey = "validation.pem" windowsConfDir = "C:/chef" ) @@ -67,6 +68,7 @@ type Provisioner struct { OSType string `mapstructure:"os_type"` PreventSudo bool `mapstructure:"prevent_sudo"` RunList []string `mapstructure:"run_list"` + SecretKeyPath string `mapstructure:"secret_key_path"` ServerURL string `mapstructure:"server_url"` SkipInstall bool `mapstructure:"skip_install"` SSLVerifyMode string `mapstructure:"ssl_verify_mode"` @@ -228,7 +230,13 @@ func (r *ResourceProvisioner) decodeConfig(c *terraform.ResourceConfig) (*Provis } p.ValidationKeyPath = keyPath } - + if p.SecretKeyPath != "" { + keyPath, err := homedir.Expand(p.SecretKeyPath) + if err != nil { + return nil, fmt.Errorf("Error expanding the secret key path: %v", err) + } + p.SecretKeyPath = keyPath + } if attrs, ok := c.Config["attributes"]; ok { p.Attributes, err = rawToJSON(attrs) if err != nil { @@ -334,7 +342,7 @@ func (p *Provisioner) deployConfigFiles( o terraform.UIOutput, comm communicator.Communicator, confDir string) error { - // Open the validation key file + // Open the validation key file f, err := os.Open(p.ValidationKeyPath) if err != nil { return err @@ -346,6 +354,20 @@ func (p *Provisioner) deployConfigFiles( return fmt.Errorf("Uploading %s failed: %v", validationKey, err) } + if p.SecretKeyPath != "" { + // Open the secret key file + s, err := os.Open(p.SecretKeyPath) + if err != nil { + return err + } + defer s.Close() + + // Copy the secret key to the new instance + if err := comm.Upload(path.Join(confDir, secretKey), s); err != nil { + return fmt.Errorf("Uploading %s failed: %v", secretKey, err) + } + } + // Make strings.Join available for use within the template funcMap := template.FuncMap{ "join": strings.Join, diff --git a/builtin/provisioners/chef/resource_provisioner_test.go b/builtin/provisioners/chef/resource_provisioner_test.go index 45fc8a211..b02c0c286 100644 --- a/builtin/provisioners/chef/resource_provisioner_test.go +++ b/builtin/provisioners/chef/resource_provisioner_test.go @@ -21,6 +21,7 @@ func TestResourceProvider_Validate_good(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }) r := new(ResourceProvisioner) warn, errs := r.Validate(c) @@ -68,6 +69,7 @@ func TestResourceProvider_runChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), ConfDir: linuxConfDir, @@ -85,6 +87,7 @@ func TestResourceProvider_runChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), ConfDir: linuxConfDir, @@ -103,6 +106,7 @@ func TestResourceProvider_runChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), ConfDir: windowsConfDir, diff --git a/builtin/provisioners/chef/test-fixtures/encrypted_data_bag_secret b/builtin/provisioners/chef/test-fixtures/encrypted_data_bag_secret new file mode 100644 index 000000000..97249fae5 --- /dev/null +++ b/builtin/provisioners/chef/test-fixtures/encrypted_data_bag_secret @@ -0,0 +1 @@ +SECRET-KEY-FILE diff --git a/builtin/provisioners/chef/windows_provisioner_test.go b/builtin/provisioners/chef/windows_provisioner_test.go index 159e7be55..443451e68 100644 --- a/builtin/provisioners/chef/windows_provisioner_test.go +++ b/builtin/provisioners/chef/windows_provisioner_test.go @@ -22,6 +22,7 @@ func TestResourceProvider_windowsInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -42,6 +43,7 @@ func TestResourceProvider_windowsInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -60,6 +62,7 @@ func TestResourceProvider_windowsInstallChefClient(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "validator.pem", + "secret_key_path": "encrypted_data_bag_secret", "version": "11.18.6", }), @@ -109,6 +112,7 @@ func TestResourceProvider_windowsCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -119,10 +123,11 @@ func TestResourceProvider_windowsCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - windowsConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - windowsConfDir + "/ohai/hints/ohaihint.json": "OHAI-HINT-FILE", - windowsConfDir + "/client.rb": defaultWindowsClientConf, - windowsConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, + windowsConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + windowsConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + windowsConfDir + "/ohai/hints/ohaihint.json": "OHAI-HINT-FILE", + windowsConfDir + "/client.rb": defaultWindowsClientConf, + windowsConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, }, }, @@ -136,6 +141,7 @@ func TestResourceProvider_windowsCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -143,9 +149,10 @@ func TestResourceProvider_windowsCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - windowsConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - windowsConfDir + "/client.rb": proxyWindowsClientConf, - windowsConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, + windowsConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + windowsConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + windowsConfDir + "/client.rb": proxyWindowsClientConf, + windowsConfDir + "/first-boot.json": `{"run_list":["cookbook::recipe"]}`, }, }, @@ -177,6 +184,7 @@ func TestResourceProvider_windowsCreateConfigFiles(t *testing.T) { "server_url": "https://chef.local", "validation_client_name": "validator", "validation_key_path": "test-fixtures/validator.pem", + "secret_key_path": "test-fixtures/encrypted_data_bag_secret", }), Commands: map[string]bool{ @@ -184,8 +192,9 @@ func TestResourceProvider_windowsCreateConfigFiles(t *testing.T) { }, Uploads: map[string]string{ - windowsConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", - windowsConfDir + "/client.rb": defaultWindowsClientConf, + windowsConfDir + "/validation.pem": "VALIDATOR-PEM-FILE", + windowsConfDir + "/encrypted_data_bag_secret": "SECRET-KEY-FILE", + windowsConfDir + "/client.rb": defaultWindowsClientConf, windowsConfDir + "/first-boot.json": `{"key1":{"subkey1":{"subkey2a":["val1","val2","val3"],` + `"subkey2b":{"subkey3":"value3"}}},"key2":"value2","run_list":["cookbook::recipe"]}`, }, diff --git a/website/source/docs/provisioners/chef.html.markdown b/website/source/docs/provisioners/chef.html.markdown index 24a682b55..d1b47db25 100644 --- a/website/source/docs/provisioners/chef.html.markdown +++ b/website/source/docs/provisioners/chef.html.markdown @@ -36,10 +36,11 @@ resource "aws_instance" "web" { environment = "_default" run_list = ["cookbook::recipe"] node_name = "webserver1" + secret_key_path = "../encrypted_data_bag_secret" server_url = "https://chef.company.com/organizations/org1" validation_client_name = "chef-validator" validation_key_path = "../chef-validator.pem" - version = "11.18.6" + version = "12.4.1" } } ``` @@ -82,6 +83,10 @@ The following arguments are supported: Chef Client run. The run-list will also be saved to the Chef Server after a successful initial run. +* `secret_key_path (string)` - (Optional) The path to the secret key that is used + by the client to decrypt data bags on the Chef Server. The key will be uploaded to the remote + machine. + * `server_url (string)` - (Required) The URL to the Chef server. This includes the path to the organization. See the example.