github.com/rhenning/terraform@v0.8.0-beta2/builtin/providers/vault/provider.go (about)

     1  package vault
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/helper/schema"
     9  	"github.com/hashicorp/terraform/terraform"
    10  	"github.com/hashicorp/vault/api"
    11  )
    12  
    13  func Provider() terraform.ResourceProvider {
    14  	return &schema.Provider{
    15  		Schema: map[string]*schema.Schema{
    16  			"address": &schema.Schema{
    17  				Type:        schema.TypeString,
    18  				Required:    true,
    19  				DefaultFunc: schema.EnvDefaultFunc("VAULT_ADDR", nil),
    20  				Description: "URL of the root of the target Vault server.",
    21  			},
    22  			"token": &schema.Schema{
    23  				Type:        schema.TypeString,
    24  				Required:    true,
    25  				DefaultFunc: schema.EnvDefaultFunc("VAULT_TOKEN", nil),
    26  				Description: "Token to use to authenticate to Vault.",
    27  			},
    28  			"ca_cert_file": &schema.Schema{
    29  				Type:          schema.TypeString,
    30  				Optional:      true,
    31  				ConflictsWith: []string{"ca_cert_dir"},
    32  				DefaultFunc:   schema.EnvDefaultFunc("VAULT_CACERT", nil),
    33  				Description:   "Path to a CA certificate file to validate the server's certificate.",
    34  			},
    35  			"ca_cert_dir": &schema.Schema{
    36  				Type:          schema.TypeString,
    37  				Optional:      true,
    38  				ConflictsWith: []string{"ca_cert_file"},
    39  				DefaultFunc:   schema.EnvDefaultFunc("VAULT_CAPATH", nil),
    40  				Description:   "Path to directory containing CA certificate files to validate the server's certificate.",
    41  			},
    42  			"client_auth": &schema.Schema{
    43  				Type:        schema.TypeList,
    44  				Optional:    true,
    45  				Description: "Client authentication credentials.",
    46  				Elem: &schema.Resource{
    47  					Schema: map[string]*schema.Schema{
    48  						"cert_file": &schema.Schema{
    49  							Type:        schema.TypeString,
    50  							Required:    true,
    51  							DefaultFunc: schema.EnvDefaultFunc("VAULT_CLIENT_CERT", nil),
    52  							Description: "Path to a file containing the client certificate.",
    53  						},
    54  						"key_file": &schema.Schema{
    55  							Type:        schema.TypeString,
    56  							Required:    true,
    57  							DefaultFunc: schema.EnvDefaultFunc("VAULT_CLIENT_KEY", nil),
    58  							Description: "Path to a file containing the private key that the certificate was issued for.",
    59  						},
    60  					},
    61  				},
    62  			},
    63  			"skip_tls_verify": &schema.Schema{
    64  				Type:        schema.TypeBool,
    65  				Optional:    true,
    66  				DefaultFunc: schema.EnvDefaultFunc("VAULT_SKIP_VERIFY", nil),
    67  				Description: "Set this to true only if the target Vault server is an insecure development instance.",
    68  			},
    69  			"max_lease_ttl_seconds": &schema.Schema{
    70  				Type:     schema.TypeInt,
    71  				Optional: true,
    72  
    73  				// Default is 20min, which is intended to be enough time for
    74  				// a reasonable Terraform run can complete but not
    75  				// significantly longer, so that any leases are revoked shortly
    76  				// after Terraform has finished running.
    77  				DefaultFunc: schema.EnvDefaultFunc("TERRAFORM_VAULT_MAX_TTL", 1200),
    78  
    79  				Description: "Maximum TTL for secret leases requested by this provider",
    80  			},
    81  		},
    82  
    83  		ConfigureFunc: providerConfigure,
    84  
    85  		DataSourcesMap: map[string]*schema.Resource{
    86  			"vault_generic_secret": genericSecretDataSource(),
    87  		},
    88  
    89  		ResourcesMap: map[string]*schema.Resource{
    90  			"vault_generic_secret": genericSecretResource(),
    91  		},
    92  	}
    93  }
    94  
    95  func providerConfigure(d *schema.ResourceData) (interface{}, error) {
    96  	config := &api.Config{
    97  		Address: d.Get("address").(string),
    98  	}
    99  
   100  	clientAuthI := d.Get("client_auth").([]interface{})
   101  	if len(clientAuthI) > 1 {
   102  		return nil, fmt.Errorf("client_auth block may appear only once")
   103  	}
   104  
   105  	clientAuthCert := ""
   106  	clientAuthKey := ""
   107  	if len(clientAuthI) == 1 {
   108  		clientAuth := clientAuthI[0].(map[string]interface{})
   109  		clientAuthCert = clientAuth["cert_file"].(string)
   110  		clientAuthKey = clientAuth["key_file"].(string)
   111  	}
   112  
   113  	config.ConfigureTLS(&api.TLSConfig{
   114  		CACert:   d.Get("ca_cert_file").(string),
   115  		CAPath:   d.Get("ca_cert_dir").(string),
   116  		Insecure: d.Get("skip_tls_verify").(bool),
   117  
   118  		ClientCert: clientAuthCert,
   119  		ClientKey:  clientAuthKey,
   120  	})
   121  
   122  	client, err := api.NewClient(config)
   123  	if err != nil {
   124  		return nil, fmt.Errorf("failed to configure Vault API: %s", err)
   125  	}
   126  
   127  	// In order to enforce our relatively-short lease TTL, we derive a
   128  	// temporary child token that inherits all of the policies of the
   129  	// token we were given but expires after max_lease_ttl_seconds.
   130  	//
   131  	// The intent here is that Terraform will need to re-fetch any
   132  	// secrets on each run and so we limit the exposure risk of secrets
   133  	// that end up stored in the Terraform state, assuming that they are
   134  	// credentials that Vault is able to revoke.
   135  	//
   136  	// Caution is still required with state files since not all secrets
   137  	// can explicitly be revoked, and this limited scope won't apply to
   138  	// any secrets that are *written* by Terraform to Vault.
   139  
   140  	client.SetToken(d.Get("token").(string))
   141  	renewable := false
   142  	childTokenLease, err := client.Auth().Token().Create(&api.TokenCreateRequest{
   143  		DisplayName:    "terraform",
   144  		TTL:            fmt.Sprintf("%ds", d.Get("max_lease_ttl_seconds").(int)),
   145  		ExplicitMaxTTL: fmt.Sprintf("%ds", d.Get("max_lease_ttl_seconds").(int)),
   146  		Renewable:      &renewable,
   147  	})
   148  	if err != nil {
   149  		return nil, fmt.Errorf("failed to create limited child token: %s", err)
   150  	}
   151  
   152  	childToken := childTokenLease.Auth.ClientToken
   153  	policies := childTokenLease.Auth.Policies
   154  
   155  	log.Printf("[INFO] Using Vault token with the following policies: %s", strings.Join(policies, ", "))
   156  
   157  	client.SetToken(childToken)
   158  
   159  	return client, nil
   160  }