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 }