github.com/hugorut/terraform@v1.1.3/src/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/hugorut/terraform/src/backend" 14 "github.com/hugorut/terraform/src/legacy/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 "user": { 30 Type: schema.TypeString, 31 Optional: true, 32 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_USER", "SDC_USER"}, ""), 33 }, 34 35 "url": { 36 Type: schema.TypeString, 37 Optional: true, 38 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"MANTA_URL"}, "https://us-east.manta.joyent.com"), 39 }, 40 41 "key_material": { 42 Type: schema.TypeString, 43 Optional: true, 44 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_MATERIAL", "SDC_KEY_MATERIAL"}, ""), 45 }, 46 47 "key_id": { 48 Type: schema.TypeString, 49 Required: true, 50 DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_ID", "SDC_KEY_ID"}, ""), 51 }, 52 53 "insecure_skip_tls_verify": { 54 Type: schema.TypeBool, 55 Optional: true, 56 DefaultFunc: schema.EnvDefaultFunc("TRITON_SKIP_TLS_VERIFY", false), 57 }, 58 59 "path": { 60 Type: schema.TypeString, 61 Required: true, 62 }, 63 64 "object_name": { 65 Type: schema.TypeString, 66 Optional: true, 67 Default: "terraform.tfstate", 68 }, 69 }, 70 } 71 72 result := &Backend{Backend: s} 73 result.Backend.ConfigureFunc = result.configure 74 return result 75 } 76 77 type Backend struct { 78 *schema.Backend 79 data *schema.ResourceData 80 81 // The fields below are set from configure 82 storageClient *storage.StorageClient 83 path string 84 objectName string 85 } 86 87 type BackendConfig struct { 88 AccountId string 89 Username string 90 KeyId string 91 AccountUrl string 92 KeyMaterial string 93 SkipTls bool 94 } 95 96 func (b *Backend) configure(ctx context.Context) error { 97 if b.path != "" { 98 return nil 99 } 100 101 data := schema.FromContextBackendConfig(ctx) 102 103 config := &BackendConfig{ 104 AccountId: data.Get("account").(string), 105 AccountUrl: data.Get("url").(string), 106 KeyId: data.Get("key_id").(string), 107 SkipTls: data.Get("insecure_skip_tls_verify").(bool), 108 } 109 110 if v, ok := data.GetOk("user"); ok { 111 config.Username = v.(string) 112 } 113 114 if v, ok := data.GetOk("key_material"); ok { 115 config.KeyMaterial = v.(string) 116 } 117 118 b.path = data.Get("path").(string) 119 b.objectName = data.Get("object_name").(string) 120 121 // If object_name is not set, try the deprecated objectName. 122 if b.objectName == "" { 123 b.objectName = data.Get("objectName").(string) 124 } 125 126 var validationError *multierror.Error 127 128 if data.Get("account").(string) == "" { 129 validationError = multierror.Append(validationError, errors.New("`Account` must be configured for the Triton provider")) 130 } 131 if data.Get("key_id").(string) == "" { 132 validationError = multierror.Append(validationError, errors.New("`Key ID` must be configured for the Triton provider")) 133 } 134 if b.path == "" { 135 validationError = multierror.Append(validationError, errors.New("`Path` must be configured for the Triton provider")) 136 } 137 138 if validationError != nil { 139 return validationError 140 } 141 142 var signer authentication.Signer 143 var err error 144 145 if config.KeyMaterial == "" { 146 input := authentication.SSHAgentSignerInput{ 147 KeyID: config.KeyId, 148 AccountName: config.AccountId, 149 Username: config.Username, 150 } 151 signer, err = authentication.NewSSHAgentSigner(input) 152 if err != nil { 153 return errwrap.Wrapf("Error Creating SSH Agent Signer: {{err}}", err) 154 } 155 } else { 156 var keyBytes []byte 157 if _, err = os.Stat(config.KeyMaterial); err == nil { 158 keyBytes, err = ioutil.ReadFile(config.KeyMaterial) 159 if err != nil { 160 return fmt.Errorf("Error reading key material from %s: %s", 161 config.KeyMaterial, err) 162 } 163 block, _ := pem.Decode(keyBytes) 164 if block == nil { 165 return fmt.Errorf( 166 "Failed to read key material '%s': no key found", config.KeyMaterial) 167 } 168 169 if block.Headers["Proc-Type"] == "4,ENCRYPTED" { 170 return fmt.Errorf( 171 "Failed to read key '%s': password protected keys are\n"+ 172 "not currently supported. Please decrypt the key prior to use.", config.KeyMaterial) 173 } 174 175 } else { 176 keyBytes = []byte(config.KeyMaterial) 177 } 178 179 input := authentication.PrivateKeySignerInput{ 180 KeyID: config.KeyId, 181 PrivateKeyMaterial: keyBytes, 182 AccountName: config.AccountId, 183 Username: config.Username, 184 } 185 186 signer, err = authentication.NewPrivateKeySigner(input) 187 if err != nil { 188 return errwrap.Wrapf("Error Creating SSH Private Key Signer: {{err}}", err) 189 } 190 } 191 192 clientConfig := &triton.ClientConfig{ 193 MantaURL: config.AccountUrl, 194 AccountName: config.AccountId, 195 Username: config.Username, 196 Signers: []authentication.Signer{signer}, 197 } 198 triton, err := storage.NewClient(clientConfig) 199 if err != nil { 200 return err 201 } 202 203 b.storageClient = triton 204 205 return nil 206 }