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