Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chef: read key contents instead of paths #3896

Merged
merged 1 commit into from
Nov 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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__.