Skip to content

Commit

Permalink
Merge pull request #3896 from hashicorp/phinze/chef-keys-as-contents
Browse files Browse the repository at this point in the history
chef: read key contents instead of paths
  • Loading branch information
Sander van Harmelen committed Nov 16, 2015
2 parents fed3095 + 73ce6d1 commit 0cdc81f
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 42 deletions.
73 changes: 38 additions & 35 deletions builtin/provisioners/chef/resource_provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import (
"io"
"log"
"os"
"path"
"path/filepath"
"regexp"
"strings"
"text/template"
"time"

"github.com/hashicorp/terraform/communicator"
"github.com/hashicorp/terraform/communicator/remote"
"github.com/hashicorp/terraform/helper/pathorcontents"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/go-homedir"
"github.com/mitchellh/go-linereader"
Expand Down Expand Up @@ -79,18 +80,22 @@ type Provisioner struct {
OSType string `mapstructure:"os_type"`
PreventSudo bool `mapstructure:"prevent_sudo"`
RunList []string `mapstructure:"run_list"`
SecretKeyPath string `mapstructure:"secret_key_path"`
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"`
ValidationKeyPath string `mapstructure:"validation_key_path"`
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

// Deprecated Fields
SecretKeyPath string `mapstructure:"secret_key_path"`
ValidationKeyPath string `mapstructure:"validation_key_path"`
}

// ResourceProvisioner represents a generic chef provisioner
Expand Down Expand Up @@ -189,15 +194,24 @@ func (r *ResourceProvisioner) Validate(c *terraform.ResourceConfig) (ws []string
if p.ValidationClientName == "" {
es = append(es, fmt.Errorf("Key not found: validation_client_name"))
}
if p.ValidationKeyPath == "" {
es = append(es, fmt.Errorf("Key not found: validation_key_path"))
if p.ValidationKey == "" && p.ValidationKeyPath == "" {
es = append(es, fmt.Errorf(
"One of validation_key or the deprecated validation_key_path must be provided"))
}
if p.UsePolicyfile && p.PolicyName == "" {
es = append(es, fmt.Errorf("Policyfile enabled but key not found: policy_name"))
}
if p.UsePolicyfile && p.PolicyGroup == "" {
es = append(es, fmt.Errorf("Policyfile enabled but key not found: policy_group"))
}
if p.ValidationKeyPath != "" {
ws = append(ws, "validation_key_path is deprecated, please use "+
"validation_key instead and load the key contents via file()")
}
if p.SecretKeyPath != "" {
ws = append(ws, "secret_key_path is deprecated, please use "+
"secret_key instead and load the key contents via file()")
}

return ws, es
}
Expand Down Expand Up @@ -247,20 +261,12 @@ func (r *ResourceProvisioner) decodeConfig(c *terraform.ResourceConfig) (*Provis
p.OhaiHints[i] = hintPath
}

if p.ValidationKeyPath != "" {
keyPath, err := homedir.Expand(p.ValidationKeyPath)
if err != nil {
return nil, fmt.Errorf("Error expanding the validation key path: %v", err)
}
p.ValidationKeyPath = keyPath
if p.ValidationKey == "" && p.ValidationKeyPath != "" {
p.ValidationKey = p.ValidationKeyPath
}

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 p.SecretKey == "" && p.SecretKeyPath != "" {
p.SecretKey = p.SecretKeyPath
}

if attrs, ok := c.Config["attributes"]; ok {
Expand Down Expand Up @@ -316,7 +322,7 @@ func (p *Provisioner) runChefClientFunc(
chefCmd string,
confDir string) func(terraform.UIOutput, communicator.Communicator) error {
return func(o terraform.UIOutput, comm communicator.Communicator) error {
fb := path.Join(confDir, firstBoot)
fb := filepath.Join(confDir, firstBoot)
var cmd string

// Policyfiles do not support chef environments, so don't pass the `-E` flag.
Expand All @@ -331,8 +337,8 @@ func (p *Provisioner) runChefClientFunc(
return fmt.Errorf("Error creating logfile directory %s: %v", logfileDir, err)
}

logFile := path.Join(logfileDir, p.NodeName)
f, err := os.Create(path.Join(logFile))
logFile := filepath.Join(logfileDir, p.NodeName)
f, err := os.Create(filepath.Join(logFile))
if err != nil {
return fmt.Errorf("Error creating logfile %s: %v", logFile, err)
}
Expand All @@ -348,7 +354,7 @@ func (p *Provisioner) runChefClientFunc(

// Output implementation of terraform.UIOutput interface
func (p *Provisioner) Output(output string) {
logFile := path.Join(logfileDir, p.NodeName)
logFile := filepath.Join(logfileDir, p.NodeName)
f, err := os.OpenFile(logFile, os.O_APPEND|os.O_WRONLY, 0666)
if err != nil {
log.Printf("Error creating logfile %s: %v", logFile, err)
Expand Down Expand Up @@ -376,28 +382,25 @@ func (p *Provisioner) deployConfigFiles(
o terraform.UIOutput,
comm communicator.Communicator,
confDir string) error {
// Open the validation key file
f, err := os.Open(p.ValidationKeyPath)
contents, _, err := pathorcontents.Read(p.ValidationKey)
if err != nil {
return err
}
defer f.Close()
f := strings.NewReader(contents)

// Copy the validation key to the new instance
if err := comm.Upload(path.Join(confDir, validationKey), f); err != nil {
if err := comm.Upload(filepath.Join(confDir, validationKey), f); err != nil {
return fmt.Errorf("Uploading %s failed: %v", validationKey, err)
}

if p.SecretKeyPath != "" {
// Open the secret key file
s, err := os.Open(p.SecretKeyPath)
if p.SecretKey != "" {
contents, _, err := pathorcontents.Read(p.SecretKey)
if err != nil {
return err
}
defer s.Close()

s := strings.NewReader(contents)
// Copy the secret key to the new instance
if err := comm.Upload(path.Join(confDir, secretKey), s); err != nil {
if err := comm.Upload(filepath.Join(confDir, secretKey), s); err != nil {
return fmt.Errorf("Uploading %s failed: %v", secretKey, err)
}
}
Expand All @@ -417,7 +420,7 @@ func (p *Provisioner) deployConfigFiles(
}

// Copy the client config to the new instance
if err := comm.Upload(path.Join(confDir, clienrb), &buf); err != nil {
if err := comm.Upload(filepath.Join(confDir, clienrb), &buf); err != nil {
return fmt.Errorf("Uploading %s failed: %v", clienrb, err)
}

Expand Down Expand Up @@ -446,7 +449,7 @@ func (p *Provisioner) deployConfigFiles(
}

// Copy the first-boot.json to the new instance
if err := comm.Upload(path.Join(confDir, firstBoot), bytes.NewReader(d)); err != nil {
if err := comm.Upload(filepath.Join(confDir, firstBoot), bytes.NewReader(d)); err != nil {
return fmt.Errorf("Uploading %s failed: %v", firstBoot, err)
}

Expand All @@ -466,8 +469,8 @@ func (p *Provisioner) deployOhaiHints(
defer f.Close()

// Copy the hint to the new instance
if err := comm.Upload(path.Join(hintDir, path.Base(hint)), f); err != nil {
return fmt.Errorf("Uploading %s failed: %v", path.Base(hint), err)
if err := comm.Upload(filepath.Join(hintDir, filepath.Base(hint)), f); err != nil {
return fmt.Errorf("Uploading %s failed: %v", filepath.Base(hint), err)
}
}

Expand Down
2 changes: 1 addition & 1 deletion builtin/provisioners/chef/resource_provisioner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func TestResourceProvider_Validate_good(t *testing.T) {
"run_list": []interface{}{"cookbook::recipe"},
"server_url": "https://chef.local",
"validation_client_name": "validator",
"validation_key_path": "validator.pem",
"validation_key": "contentsofsomevalidator.pem",
})
r := new(ResourceProvisioner)
warn, errs := r.Validate(c)
Expand Down
20 changes: 14 additions & 6 deletions website/source/docs/provisioners/chef.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ resource "aws_instance" "web" {
environment = "_default"
run_list = ["cookbook::recipe"]
node_name = "webserver1"
secret_key_path = "../encrypted_data_bag_secret"
secret_key = "${file("../encrypted_data_bag_secret")}"
server_url = "https://chef.company.com/organizations/org1"
validation_client_name = "chef-validator"
validation_key_path = "../chef-validator.pem"
validation_key = "${file("../chef-validator.pem")}"
version = "12.4.1"
}
}
Expand Down Expand Up @@ -83,9 +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
* `secret_key (string)` - (Optional) The contents of 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.
machine. These can be loaded from a file on disk using the [`file()` interpolation
function](/docs/configuration/interpolation.html#file_path_).

* `server_url (string)` - (Required) The URL to the Chef server. This includes the path to
the organization. See the example.
Expand All @@ -100,9 +101,16 @@ The following arguments are supported:
* `validation_client_name (string)` - (Required) The name of the validation client to use
for the initial communication with the Chef Server.

* `validation_key_path (string)` - (Required) The path to the validation key that is needed
* `validation_key (string)` - (Required) The contents of the validation key that is needed
by the node to register itself with the Chef Server. The key will be uploaded to the remote
machine.
machine. These can be loaded from a file on disk using the [`file()`
interpolation function](/docs/configuration/interpolation.html#file_path_).

* `version (string)` - (Optional) The Chef Client version to install on the remote machine.
If not set the latest available version will be installed.

These are supported for backwards compatibility and may be removed in a
future version:

* `validation_key_path (string)` - __Deprecated: please use `validation_key` instead__.
* `secret_key_path (string)` - __Deprecated: please use `secret_key` instead__.

0 comments on commit 0cdc81f

Please sign in to comment.