Merge pull request #14077 from hashicorp/triton-allow-insecure

provider/triton: Add `insecure_skip_tls_verify`
This commit is contained in:
Jake Champlin 2017-04-28 16:26:43 -04:00 committed by GitHub
commit ba52f8045f
12 changed files with 133 additions and 45 deletions

View File

@ -42,6 +42,12 @@ func Provider() terraform.ResourceProvider {
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", ""),
},
},
ResourcesMap: map[string]*schema.Resource{
@ -56,10 +62,11 @@ func Provider() terraform.ResourceProvider {
}
type Config struct {
Account string
KeyMaterial string
KeyID string
URL string
Account string
KeyMaterial string
KeyID string
URL string
InsecureSkipTLSVerify bool
}
func (c Config) validate() error {
@ -98,6 +105,10 @@ func (c Config) getTritonClient() (*triton.Client, error) {
return nil, errwrap.Wrapf("Error Creating Triton Client: {{err}}", err)
}
if c.InsecureSkipTLSVerify {
client.InsecureSkipTLSVerify()
}
return client, nil
}
@ -106,6 +117,8 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) {
Account: d.Get("account").(string),
URL: d.Get("url").(string),
KeyID: d.Get("key_id").(string),
InsecureSkipTLSVerify: d.Get("insecure_skip_tls_verify").(bool),
}
if keyMaterial, ok := d.GetOk("key_material"); ok {

View File

@ -5,8 +5,9 @@ import (
"net/http"
"time"
"github.com/hashicorp/errwrap"
"fmt"
"github.com/hashicorp/errwrap"
)
type AccountsClient struct {
@ -40,7 +41,8 @@ type Account struct {
type GetAccountInput struct{}
func (client *AccountsClient) GetAccount(input *GetAccountInput) (*Account, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my", nil)
path := fmt.Sprintf("/%s", client.accountName)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}
@ -58,17 +60,17 @@ func (client *AccountsClient) GetAccount(input *GetAccountInput) (*Account, erro
}
type UpdateAccountInput struct {
Email string `json:"email,omitempty"`
CompanyName string `json:"companyName,omitempty"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
Address string `json:"address,omitempty"`
PostalCode string `json:"postalCode,omitempty"`
City string `json:"city,omitempty"`
State string `json:"state,omitempty"`
Country string `json:"country,omitempty"`
Phone string `json:"phone,omitempty"`
TritonCNSEnabled bool `json:"triton_cns_enabled,omitempty"`
Email string `json:"email,omitempty"`
CompanyName string `json:"companyName,omitempty"`
FirstName string `json:"firstName,omitempty"`
LastName string `json:"lastName,omitempty"`
Address string `json:"address,omitempty"`
PostalCode string `json:"postalCode,omitempty"`
City string `json:"city,omitempty"`
State string `json:"state,omitempty"`
Country string `json:"country,omitempty"`
Phone string `json:"phone,omitempty"`
TritonCNSEnabled bool `json:"triton_cns_enabled,omitempty"`
}
// UpdateAccount updates your account details with the given parameters.

View File

@ -2,6 +2,7 @@ package triton
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io"
@ -45,16 +46,7 @@ func NewClient(endpoint string, accountName string, signers ...authentication.Si
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
DisableKeepAlives: true,
MaxIdleConnsPerHost: -1,
},
Transport: httpTransport(false),
CheckRedirect: doNotFollowRedirects,
}
@ -75,6 +67,34 @@ func NewClient(endpoint string, accountName string, signers ...authentication.Si
}, nil
}
// InsecureSkipTLSVerify turns off TLS verification for the client connection. This
// allows connection to an endpoint with a certificate which was signed by a non-
// trusted CA, such as self-signed certificates. This can be useful when connecting
// to temporary Triton installations such as Triton Cloud-On-A-Laptop.
func (c *Client) InsecureSkipTLSVerify() {
if c.client == nil {
return
}
c.client.HTTPClient.Transport = httpTransport(true)
}
func httpTransport(insecureSkipTLSVerify bool) *http.Transport {
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
DisableKeepAlives: true,
MaxIdleConnsPerHost: -1,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: insecureSkipTLSVerify,
},
}
}
func doNotFollowRedirects(*http.Request, []*http.Request) error {
return http.ErrUseLastResponse
}

View File

@ -28,7 +28,8 @@ type DataCenter struct {
type ListDataCentersInput struct{}
func (client *DataCentersClient) ListDataCenters(*ListDataCentersInput) ([]*DataCenter, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my/datacenters", nil)
path := fmt.Sprintf("/%s/datacenters", client.accountName)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}
@ -68,7 +69,8 @@ type GetDataCenterInput struct {
}
func (client *DataCentersClient) GetDataCenter(input *GetDataCenterInput) (*DataCenter, error) {
resp, err := client.executeRequestRaw(http.MethodGet, fmt.Sprintf("/my/datacenters/%s", input.Name), nil)
path := fmt.Sprintf("/%s/datacenters/%s", client.accountName, input.Name)
resp, err := client.executeRequestRaw(http.MethodGet, path, nil)
if err != nil {
return nil, errwrap.Wrapf("Error executing GetDatacenter request: {{err}}", err)
}

View File

@ -27,7 +27,8 @@ type FabricVLAN struct {
type ListFabricVLANsInput struct{}
func (client *FabricsClient) ListFabricVLANs(*ListFabricVLANsInput) ([]*FabricVLAN, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my/fabrics/default/vlans", nil)
path := fmt.Sprintf("/%s/fabrics/default/vlans", client.accountName)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}

View File

@ -39,7 +39,8 @@ type FirewallRule struct {
type ListFirewallRulesInput struct{}
func (client *FirewallClient) ListFirewallRules(*ListFirewallRulesInput) ([]*FirewallRule, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my/fwrules", nil)
path := fmt.Sprintf("/%s/fwrules", client.accountName)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}
@ -194,7 +195,8 @@ type ListMachineFirewallRulesInput struct {
}
func (client *FirewallClient) ListMachineFirewallRules(input *ListMachineFirewallRulesInput) ([]*FirewallRule, error) {
respReader, err := client.executeRequest(http.MethodGet, fmt.Sprintf("/my/machines/%s/firewallrules", input.MachineID), nil)
path := fmt.Sprintf("/%s/machines/%s/firewallrules", client.accountName, input.MachineID)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}

View File

@ -49,7 +49,8 @@ type Image struct {
type ListImagesInput struct{}
func (client *ImagesClient) ListImages(*ListImagesInput) ([]*Image, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my/images", nil)
path := fmt.Sprintf("/%s/images", client.accountName)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}
@ -148,7 +149,7 @@ type CreateImageFromMachineInput struct {
HomePage string `json:"homepage,omitempty"`
EULA string `json:"eula,omitempty"`
ACL []string `json:"acl,omitempty"`
tags map[string]string `json:"tags,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
}
func (client *ImagesClient) CreateImageFromMachine(input *CreateImageFromMachineInput) (*Image, error) {
@ -178,7 +179,7 @@ type UpdateImageInput struct {
HomePage string `json:"homepage,omitempty"`
EULA string `json:"eula,omitempty"`
ACL []string `json:"acl,omitempty"`
tags map[string]string `json:"tags,omitempty"`
Tags map[string]string `json:"tags,omitempty"`
}
func (client *ImagesClient) UpdateImage(input *UpdateImageInput) (*Image, error) {

View File

@ -35,7 +35,8 @@ type ListKeysInput struct{}
// ListKeys lists all public keys we have on record for the specified
// account.
func (client *KeysClient) ListKeys(*ListKeysInput) ([]*Key, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my/keys", nil)
path := fmt.Sprintf("/%s/keys")
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}

View File

@ -100,7 +100,7 @@ func (client *MachinesClient) GetMachine(input *GetMachineInput) (*Machine, erro
if response != nil {
defer response.Body.Close()
}
if response.StatusCode == http.StatusNotFound {
if response.StatusCode == http.StatusNotFound || response.StatusCode == http.StatusGone {
return nil, &TritonError{
Code: "ResourceNotFound",
}
@ -219,7 +219,8 @@ func (input *CreateMachineInput) toAPI() map[string]interface{} {
}
func (client *MachinesClient) CreateMachine(input *CreateMachineInput) (*Machine, error) {
respReader, err := client.executeRequest(http.MethodPost, "/my/machines", input.toAPI())
path := fmt.Sprintf("/%s/machines", client.accountName)
respReader, err := client.executeRequest(http.MethodPost, path, input.toAPI())
if respReader != nil {
defer respReader.Close()
}
@ -501,7 +502,8 @@ type ListNICsInput struct {
}
func (client *MachinesClient) ListNICs(input *ListNICsInput) ([]*NIC, error) {
respReader, err := client.executeRequest(http.MethodGet, fmt.Sprintf("/my/machines/%s/nics", input.MachineID), nil)
path := fmt.Sprintf("/%s/machines/%s/nics", client.accountName, input.MachineID)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}
@ -560,6 +562,48 @@ func (client *MachinesClient) RemoveNIC(input *RemoveNICInput) error {
return nil
}
type StopMachineInput struct {
MachineID string
}
func (client *MachinesClient) StopMachine(input *StopMachineInput) error {
path := fmt.Sprintf("/%s/machines/%s", client.accountName, input.MachineID)
params := &url.Values{}
params.Set("action", "stop")
respReader, err := client.executeRequestURIParams(http.MethodPost, path, nil, params)
if respReader != nil {
defer respReader.Close()
}
if err != nil {
return errwrap.Wrapf("Error executing StopMachine request: {{err}}", err)
}
return nil
}
type StartMachineInput struct {
MachineID string
}
func (client *MachinesClient) StartMachine(input *StartMachineInput) error {
path := fmt.Sprintf("/%s/machines/%s", client.accountName, input.MachineID)
params := &url.Values{}
params.Set("action", "start")
respReader, err := client.executeRequestURIParams(http.MethodPost, path, nil, params)
if respReader != nil {
defer respReader.Close()
}
if err != nil {
return errwrap.Wrapf("Error executing StartMachine request: {{err}}", err)
}
return nil
}
var reservedMachineCNSTags = map[string]struct{}{
machineCNSTagDisable: {},
machineCNSTagReversePTR: {},

View File

@ -36,7 +36,8 @@ type Network struct {
type ListNetworksInput struct{}
func (client *NetworksClient) ListNetworks(*ListNetworksInput) ([]*Network, error) {
respReader, err := client.executeRequest(http.MethodGet, "/my/networks", nil)
path := fmt.Sprintf("/%s/networks", client.accountName)
respReader, err := client.executeRequest(http.MethodGet, path, nil)
if respReader != nil {
defer respReader.Close()
}

10
vendor/vendor.json vendored
View File

@ -2341,16 +2341,16 @@
"revisionTime": "2016-06-16T18:50:15Z"
},
{
"checksumSHA1": "2HimxaJVVp2QDVQ0570L71Zd5s4=",
"checksumSHA1": "XsjyaC6eTHUy/n0iuR46TZcgAK8=",
"path": "github.com/joyent/triton-go",
"revision": "5db9e2b6a4c1f7ffd2a7e7aa625f42dba956608c",
"revisionTime": "2017-04-12T23:23:58Z"
"revision": "c73729fd38522591909a371c8180ca7090a59ab9",
"revisionTime": "2017-04-28T18:47:44Z"
},
{
"checksumSHA1": "QzUqkCSn/ZHyIK346xb9V6EBw9U=",
"path": "github.com/joyent/triton-go/authentication",
"revision": "66b31a94af28a65e902423879a2820ea34b773fb",
"revisionTime": "2017-03-31T18:12:29Z"
"revision": "c73729fd38522591909a371c8180ca7090a59ab9",
"revisionTime": "2017-04-28T18:47:44Z"
},
{
"checksumSHA1": "YhQcOsGx8r2S/jkJ0Qt4cZ5BLCU=",

View File

@ -33,3 +33,4 @@ The following arguments are supported in the `provider` block:
* `key_material` - (Optional) This is the private key of an SSH key associated with the Triton account to be used. If this is not set, the private key corresponding to the fingerprint in `key_id` must be available via an SSH Agent.
* `key_id` - (Required) This is the fingerprint of the public key matching the key specified in `key_path`. It can be obtained via the command `ssh-keygen -l -E md5 -f /path/to/key`
* `url` - (Optional) This is the URL to the Triton API endpoint. It is required if using a private installation of Triton. The default is to use the Joyent public cloud us-west-1 endpoint. Valid public cloud endpoints include: `us-east-1`, `us-east-2`, `us-east-3`, `us-sw-1`, `us-west-1`, `eu-ams-1`
* `insecure_skip_tls_verify` (Optional - defaults to false) This allows skipping TLS verification of the Triton endpoint. It is useful when connecting to a temporary Triton installation such as Cloud-On-A-Laptop which does not generally use a certificate signed by a trusted root CA.