github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/backend/remote-state/manta/backend.go (about) 1 package manta 2 3 import ( 4 "context" 5 "encoding/pem" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "os" 10 11 "github.com/hashicorp/errwrap" 12 "github.com/hashicorp/go-multierror" 13 "github.com/hashicorp/terraform/backend" 14 "github.com/hashicorp/terraform/helper/schema" 15 triton "github.com/joyent/triton-go" 16 "github.com/joyent/triton-go/authentication" 17 "github.com/joyent/triton-go/storage" 18 ) 19 20 func New() backend.Backend { 21 s := &schema.Backend{ 22 Schema: map[string]*schema.Schema{ 23 "account": { 24 Type: schema.TypeString, 25 Required: true, 26 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_ACCOUNT", "SDC_ACCOUNT"}, ""), 27 }, 28 29 "url": { 30 Type: schema.TypeString, 31 Optional: true, 32 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"MANTA_URL"}, "https://us-east.manta.joyent.com"), 33 }, 34 35 "key_material": { 36 Type: schema.TypeString, 37 Optional: true, 38 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_MATERIAL", "SDC_KEY_MATERIAL"}, ""), 39 }, 40 41 "key_id": { 42 Type: schema.TypeString, 43 Required: true, 44 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_ID", "SDC_KEY_ID"}, ""), 45 }, 46 47 "insecure_skip_tls_verify": { 48 Type: schema.TypeBool, 49 Optional: true, 50 DefaultFunc: schema.EnvDefaultFunc("TRITON_SKIP_TLS_VERIFY", ""), 51 }, 52 53 "path": { 54 Type: schema.TypeString, 55 Required: true, 56 }, 57 58 "objectName": { 59 Type: schema.TypeString, 60 Optional: true, 61 Default: "terraform.tfstate", 62 }, 63 }, 64 } 65 66 result := &Backend{Backend: s} 67 result.Backend.ConfigureFunc = result.configure 68 return result 69 } 70 71 type Backend struct { 72 *schema.Backend 73 data *schema.ResourceData 74 75 // The fields below are set from configure 76 storageClient *storage.StorageClient 77 path string 78 objectName string 79 } 80 81 type BackendConfig struct { 82 AccountId string 83 KeyId string 84 AccountUrl string 85 KeyMaterial string 86 SkipTls bool 87 } 88 89 func (b *Backend) configure(ctx context.Context) error { 90 if b.path != "" { 91 return nil 92 } 93 94 data := schema.FromContextBackendConfig(ctx) 95 96 config := &BackendConfig{ 97 AccountId: data.Get("account").(string), 98 AccountUrl: data.Get("url").(string), 99 KeyId: data.Get("key_id").(string), 100 SkipTls: data.Get("insecure_skip_tls_verify").(bool), 101 } 102 103 if v, ok := data.GetOk("key_material"); ok { 104 config.KeyMaterial = v.(string) 105 } 106 107 b.path = data.Get("path").(string) 108 b.objectName = data.Get("objectName").(string) 109 110 var validationError *multierror.Error 111 112 if data.Get("account").(string) == "" { 113 validationError = multierror.Append(validationError, errors.New("`Account` must be configured for the Triton provider")) 114 } 115 if data.Get("key_id").(string) == "" { 116 validationError = multierror.Append(validationError, errors.New("`Key ID` must be configured for the Triton provider")) 117 } 118 if b.path == "" { 119 validationError = multierror.Append(validationError, errors.New("`Path` must be configured for the Triton provider")) 120 } 121 122 if validationError != nil { 123 return validationError 124 } 125 126 var signer authentication.Signer 127 var err error 128 129 if config.KeyMaterial == "" { 130 signer, err = authentication.NewSSHAgentSigner(config.KeyId, config.AccountId) 131 if err != nil { 132 return errwrap.Wrapf("Error Creating SSH Agent Signer: {{err}}", err) 133 } 134 } else { 135 var keyBytes []byte 136 if _, err = os.Stat(config.KeyMaterial); err == nil { 137 keyBytes, err = ioutil.ReadFile(config.KeyMaterial) 138 if err != nil { 139 return fmt.Errorf("Error reading key material from %s: %s", 140 config.KeyMaterial, err) 141 } 142 block, _ := pem.Decode(keyBytes) 143 if block == nil { 144 return fmt.Errorf( 145 "Failed to read key material '%s': no key found", config.KeyMaterial) 146 } 147 148 if block.Headers["Proc-Type"] == "4,ENCRYPTED" { 149 return fmt.Errorf( 150 "Failed to read key '%s': password protected keys are\n"+ 151 "not currently supported. Please decrypt the key prior to use.", config.KeyMaterial) 152 } 153 154 } else { 155 keyBytes = []byte(config.KeyMaterial) 156 } 157 158 signer, err = authentication.NewPrivateKeySigner(config.KeyId, keyBytes, config.AccountId) 159 if err != nil { 160 return errwrap.Wrapf("Error Creating SSH Private Key Signer: {{err}}", err) 161 } 162 } 163 164 clientConfig := &triton.ClientConfig{ 165 MantaURL: config.AccountUrl, 166 AccountName: config.AccountId, 167 Signers: []authentication.Signer{signer}, 168 } 169 triton, err := storage.NewClient(clientConfig) 170 if err != nil { 171 return err 172 } 173 174 b.storageClient = triton 175 176 return nil 177 }