mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-15 19:22:46 -06:00
73dda868cc
This is part of a general effort to move all of Terraform's non-library package surface under internal in order to reinforce that these are for internal use within Terraform only. If you were previously importing packages under this prefix into an external codebase, you could pin to an earlier release tag as an interim solution until you've make a plan to achieve the same functionality some other way.
207 lines
5.1 KiB
Go
207 lines
5.1 KiB
Go
package manta
|
|
|
|
import (
|
|
"context"
|
|
"encoding/pem"
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
|
|
"github.com/hashicorp/errwrap"
|
|
"github.com/hashicorp/go-multierror"
|
|
"github.com/hashicorp/terraform/internal/backend"
|
|
"github.com/hashicorp/terraform/internal/legacy/helper/schema"
|
|
triton "github.com/joyent/triton-go"
|
|
"github.com/joyent/triton-go/authentication"
|
|
"github.com/joyent/triton-go/storage"
|
|
)
|
|
|
|
func New() backend.Backend {
|
|
s := &schema.Backend{
|
|
Schema: map[string]*schema.Schema{
|
|
"account": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_ACCOUNT", "SDC_ACCOUNT"}, ""),
|
|
},
|
|
|
|
"user": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_USER", "SDC_USER"}, ""),
|
|
},
|
|
|
|
"url": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"MANTA_URL"}, "https://us-east.manta.joyent.com"),
|
|
},
|
|
|
|
"key_material": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_MATERIAL", "SDC_KEY_MATERIAL"}, ""),
|
|
},
|
|
|
|
"key_id": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
DefaultFunc: schema.MultiEnvDefaultFunc([]string{"TRITON_KEY_ID", "SDC_KEY_ID"}, ""),
|
|
},
|
|
|
|
"insecure_skip_tls_verify": {
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("TRITON_SKIP_TLS_VERIFY", false),
|
|
},
|
|
|
|
"path": {
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
},
|
|
|
|
"object_name": {
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Default: "terraform.tfstate",
|
|
},
|
|
},
|
|
}
|
|
|
|
result := &Backend{Backend: s}
|
|
result.Backend.ConfigureFunc = result.configure
|
|
return result
|
|
}
|
|
|
|
type Backend struct {
|
|
*schema.Backend
|
|
data *schema.ResourceData
|
|
|
|
// The fields below are set from configure
|
|
storageClient *storage.StorageClient
|
|
path string
|
|
objectName string
|
|
}
|
|
|
|
type BackendConfig struct {
|
|
AccountId string
|
|
Username string
|
|
KeyId string
|
|
AccountUrl string
|
|
KeyMaterial string
|
|
SkipTls bool
|
|
}
|
|
|
|
func (b *Backend) configure(ctx context.Context) error {
|
|
if b.path != "" {
|
|
return nil
|
|
}
|
|
|
|
data := schema.FromContextBackendConfig(ctx)
|
|
|
|
config := &BackendConfig{
|
|
AccountId: data.Get("account").(string),
|
|
AccountUrl: data.Get("url").(string),
|
|
KeyId: data.Get("key_id").(string),
|
|
SkipTls: data.Get("insecure_skip_tls_verify").(bool),
|
|
}
|
|
|
|
if v, ok := data.GetOk("user"); ok {
|
|
config.Username = v.(string)
|
|
}
|
|
|
|
if v, ok := data.GetOk("key_material"); ok {
|
|
config.KeyMaterial = v.(string)
|
|
}
|
|
|
|
b.path = data.Get("path").(string)
|
|
b.objectName = data.Get("object_name").(string)
|
|
|
|
// If object_name is not set, try the deprecated objectName.
|
|
if b.objectName == "" {
|
|
b.objectName = data.Get("objectName").(string)
|
|
}
|
|
|
|
var validationError *multierror.Error
|
|
|
|
if data.Get("account").(string) == "" {
|
|
validationError = multierror.Append(validationError, errors.New("`Account` must be configured for the Triton provider"))
|
|
}
|
|
if data.Get("key_id").(string) == "" {
|
|
validationError = multierror.Append(validationError, errors.New("`Key ID` must be configured for the Triton provider"))
|
|
}
|
|
if b.path == "" {
|
|
validationError = multierror.Append(validationError, errors.New("`Path` must be configured for the Triton provider"))
|
|
}
|
|
|
|
if validationError != nil {
|
|
return validationError
|
|
}
|
|
|
|
var signer authentication.Signer
|
|
var err error
|
|
|
|
if config.KeyMaterial == "" {
|
|
input := authentication.SSHAgentSignerInput{
|
|
KeyID: config.KeyId,
|
|
AccountName: config.AccountId,
|
|
Username: config.Username,
|
|
}
|
|
signer, err = authentication.NewSSHAgentSigner(input)
|
|
if err != nil {
|
|
return errwrap.Wrapf("Error Creating SSH Agent Signer: {{err}}", err)
|
|
}
|
|
} else {
|
|
var keyBytes []byte
|
|
if _, err = os.Stat(config.KeyMaterial); err == nil {
|
|
keyBytes, err = ioutil.ReadFile(config.KeyMaterial)
|
|
if err != nil {
|
|
return fmt.Errorf("Error reading key material from %s: %s",
|
|
config.KeyMaterial, err)
|
|
}
|
|
block, _ := pem.Decode(keyBytes)
|
|
if block == nil {
|
|
return fmt.Errorf(
|
|
"Failed to read key material '%s': no key found", config.KeyMaterial)
|
|
}
|
|
|
|
if block.Headers["Proc-Type"] == "4,ENCRYPTED" {
|
|
return fmt.Errorf(
|
|
"Failed to read key '%s': password protected keys are\n"+
|
|
"not currently supported. Please decrypt the key prior to use.", config.KeyMaterial)
|
|
}
|
|
|
|
} else {
|
|
keyBytes = []byte(config.KeyMaterial)
|
|
}
|
|
|
|
input := authentication.PrivateKeySignerInput{
|
|
KeyID: config.KeyId,
|
|
PrivateKeyMaterial: keyBytes,
|
|
AccountName: config.AccountId,
|
|
Username: config.Username,
|
|
}
|
|
|
|
signer, err = authentication.NewPrivateKeySigner(input)
|
|
if err != nil {
|
|
return errwrap.Wrapf("Error Creating SSH Private Key Signer: {{err}}", err)
|
|
}
|
|
}
|
|
|
|
clientConfig := &triton.ClientConfig{
|
|
MantaURL: config.AccountUrl,
|
|
AccountName: config.AccountId,
|
|
Username: config.Username,
|
|
Signers: []authentication.Signer{signer},
|
|
}
|
|
triton, err := storage.NewClient(clientConfig)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
b.storageClient = triton
|
|
|
|
return nil
|
|
}
|