This fixes issue #4881 by adding an option to fetch the Chef SSL
certificates.
This commit is contained in:
Sander van Harmelen 2016-02-04 15:31:24 +01:00
parent da927fcd08
commit 79e2642dab
3 changed files with 139 additions and 38 deletions

View File

@ -24,16 +24,18 @@ import (
)
const (
clienrb = "client.rb"
defaultEnv = "_default"
firstBoot = "first-boot.json"
logfileDir = "logfiles"
linuxChefCmd = "chef-client"
linuxConfDir = "/etc/chef"
secretKey = "encrypted_data_bag_secret"
validationKey = "validation.pem"
windowsChefCmd = "cmd /c chef-client"
windowsConfDir = "C:/chef"
clienrb = "client.rb"
defaultEnv = "_default"
firstBoot = "first-boot.json"
logfileDir = "logfiles"
linuxChefCmd = "chef-client"
linuxKnifeCmd = "knife"
linuxConfDir = "/etc/chef"
secretKey = "encrypted_data_bag_secret"
validationKey = "validation.pem"
windowsChefCmd = "cmd /c chef-client"
windowsKnifeCmd = "cmd /c knife"
windowsConfDir = "C:/chef"
)
const clientConf = `
@ -74,34 +76,36 @@ ENV['no_proxy'] = "{{ join .NOProxy "," }}"
// Provisioner represents a specificly configured chef provisioner
type Provisioner struct {
Attributes interface{} `mapstructure:"attributes"`
ClientOptions []string `mapstructure:"client_options"`
DisableReporting bool `mapstructure:"disable_reporting"`
Environment string `mapstructure:"environment"`
LogToFile bool `mapstructure:"log_to_file"`
UsePolicyfile bool `mapstructure:"use_policyfile"`
PolicyGroup string `mapstructure:"policy_group"`
PolicyName string `mapstructure:"policy_name"`
HTTPProxy string `mapstructure:"http_proxy"`
HTTPSProxy string `mapstructure:"https_proxy"`
NOProxy []string `mapstructure:"no_proxy"`
NodeName string `mapstructure:"node_name"`
OhaiHints []string `mapstructure:"ohai_hints"`
OSType string `mapstructure:"os_type"`
PreventSudo bool `mapstructure:"prevent_sudo"`
RunList []string `mapstructure:"run_list"`
SecretKey string `mapstructure:"secret_key"`
ServerURL string `mapstructure:"server_url"`
SkipInstall bool `mapstructure:"skip_install"`
SSLVerifyMode string `mapstructure:"ssl_verify_mode"`
ValidationClientName string `mapstructure:"validation_client_name"`
ValidationKey string `mapstructure:"validation_key"`
Version string `mapstructure:"version"`
Attributes interface{} `mapstructure:"attributes"`
ClientOptions []string `mapstructure:"client_options"`
DisableReporting bool `mapstructure:"disable_reporting"`
Environment string `mapstructure:"environment"`
FetchChefCertificates bool `mapstructure:"fetch_chef_certificates"`
LogToFile bool `mapstructure:"log_to_file"`
UsePolicyfile bool `mapstructure:"use_policyfile"`
PolicyGroup string `mapstructure:"policy_group"`
PolicyName string `mapstructure:"policy_name"`
HTTPProxy string `mapstructure:"http_proxy"`
HTTPSProxy string `mapstructure:"https_proxy"`
NOProxy []string `mapstructure:"no_proxy"`
NodeName string `mapstructure:"node_name"`
OhaiHints []string `mapstructure:"ohai_hints"`
OSType string `mapstructure:"os_type"`
PreventSudo bool `mapstructure:"prevent_sudo"`
RunList []string `mapstructure:"run_list"`
SecretKey string `mapstructure:"secret_key"`
ServerURL string `mapstructure:"server_url"`
SkipInstall bool `mapstructure:"skip_install"`
SSLVerifyMode string `mapstructure:"ssl_verify_mode"`
ValidationClientName string `mapstructure:"validation_client_name"`
ValidationKey string `mapstructure:"validation_key"`
Version string `mapstructure:"version"`
installChefClient func(terraform.UIOutput, communicator.Communicator) error
createConfigFiles func(terraform.UIOutput, communicator.Communicator) error
runChefClient func(terraform.UIOutput, communicator.Communicator) error
useSudo bool
installChefClient func(terraform.UIOutput, communicator.Communicator) error
createConfigFiles func(terraform.UIOutput, communicator.Communicator) error
fetchChefCertificates func(terraform.UIOutput, communicator.Communicator) error
runChefClient func(terraform.UIOutput, communicator.Communicator) error
useSudo bool
// Deprecated Fields
SecretKeyPath string `mapstructure:"secret_key_path"`
@ -138,11 +142,13 @@ func (r *ResourceProvisioner) Apply(
case "linux":
p.installChefClient = p.linuxInstallChefClient
p.createConfigFiles = p.linuxCreateConfigFiles
p.fetchChefCertificates = p.fetchChefCertificatesFunc(linuxChefCmd, linuxConfDir)
p.runChefClient = p.runChefClientFunc(linuxChefCmd, linuxConfDir)
p.useSudo = !p.PreventSudo && s.Ephemeral.ConnInfo["user"] != "root"
case "windows":
p.installChefClient = p.windowsInstallChefClient
p.createConfigFiles = p.windowsCreateConfigFiles
p.fetchChefCertificates = p.fetchChefCertificatesFunc(windowsChefCmd, windowsConfDir)
p.runChefClient = p.runChefClientFunc(windowsChefCmd, windowsConfDir)
p.useSudo = false
default:
@ -176,6 +182,13 @@ func (r *ResourceProvisioner) Apply(
return err
}
if p.FetchChefCertificates {
o.Output("Fetch Chef certificates...")
if err := p.fetchChefCertificates(o, comm); err != nil {
return err
}
}
o.Output("Starting initial Chef-Client run...")
if err := p.runChefClient(o, comm); err != nil {
return err
@ -343,6 +356,17 @@ func retryFunc(timeout time.Duration, f func() error) error {
}
}
func (p *Provisioner) fetchChefCertificatesFunc(
knifeCmd string,
confDir string) func(terraform.UIOutput, communicator.Communicator) error {
return func(o terraform.UIOutput, comm communicator.Communicator) error {
clientrb := path.Join(confDir, clienrb)
cmd := fmt.Sprintf("%s ssl fetch -c %s", knifeCmd, clientrb)
return p.runCommand(o, comm, cmd)
}
}
func (p *Provisioner) runChefClientFunc(
chefCmd string,
confDir string) func(terraform.UIOutput, communicator.Communicator) error {

View File

@ -148,3 +148,76 @@ func TestResourceProvider_runChefClient(t *testing.T) {
}
}
}
func TestResourceProvider_fetchChefCertificates(t *testing.T) {
cases := map[string]struct {
Config *terraform.ResourceConfig
KnifeCmd string
ConfDir string
Commands map[string]bool
}{
"Sudo": {
Config: testConfig(t, map[string]interface{}{
"fetch_chef_certificates": true,
"node_name": "nodename1",
"run_list": []interface{}{"cookbook::recipe"},
"server_url": "https://chef.local",
"validation_client_name": "validator",
"validation_key_path": "test-fixtures/validator.pem",
}),
KnifeCmd: linuxKnifeCmd,
ConfDir: linuxConfDir,
Commands: map[string]bool{
fmt.Sprintf(`sudo %s ssl fetch -c %s`,
linuxKnifeCmd,
path.Join(linuxConfDir, "client.rb")): true,
},
},
"NoSudo": {
Config: testConfig(t, map[string]interface{}{
"fetch_chef_certificates": true,
"node_name": "nodename1",
"prevent_sudo": true,
"run_list": []interface{}{"cookbook::recipe"},
"server_url": "https://chef.local",
"validation_client_name": "validator",
"validation_key_path": "test-fixtures/validator.pem",
}),
KnifeCmd: windowsKnifeCmd,
ConfDir: windowsConfDir,
Commands: map[string]bool{
fmt.Sprintf(`%s ssl fetch -c %s`,
windowsKnifeCmd,
path.Join(windowsConfDir, "client.rb")): true,
},
},
}
r := new(ResourceProvisioner)
o := new(terraform.MockUIOutput)
c := new(communicator.MockCommunicator)
for k, tc := range cases {
c.Commands = tc.Commands
p, err := r.decodeConfig(tc.Config)
if err != nil {
t.Fatalf("Error: %v", err)
}
p.fetchChefCertificates = p.fetchChefCertificatesFunc(tc.KnifeCmd, tc.ConfDir)
p.useSudo = !p.PreventSudo
err = p.fetchChefCertificates(o, c)
if err != nil {
t.Fatalf("Test %q failed: %v", k, err)
}
}
}

View File

@ -59,7 +59,7 @@ The following arguments are supported:
interpolation function](/docs/configuration/interpolation.html#file_path_).
* `client_options (array)` - (Optional) A list of optional Chef Client configuration
options. See the Chef Client [documentation](https://docs.chef.io/config_rb_client.html) for all available options.
options. See the [Chef Client ](https://docs.chef.io/config_rb_client.html) documentation for all available options.
* `disable_reporting (boolean)` - (Optional) If true the Chef Client will not try to send
reporting data (used by Chef Reporting) to the Chef Server (defaults false)
@ -67,6 +67,10 @@ The following arguments are supported:
* `environment (string)` - (Optional) The Chef environment the new node will be joining
(defaults `_default`).
* `fetch_chef_certificates (boolean)` (Optional) If true the SSL certificates configured
on your Chef server will be fetched and trusted. See the knife [ssl_fetch](https://docs.chef.io/knife_ssl_fetch.html)
documentation for more details.
* `log_to_file (boolean)` - (Optional) If true, the output of the initial Chef Client run
will be logged to a local file instead of the console. The file will be created in a
subdirectory called `logfiles` created in your current directory. The filename will be