- re-add ‘testAccPreCheck()’ to acceptance tests, to ensure necessary GOOGLE_* env vars are set for Acceptance tests.
- remove unused code from datasource
- use URL signature (base64 encoded) as data source ID instead of full URL
This commit is contained in:
Matt Morrison 2016-08-15 17:34:56 +12:00 committed by Matt Morrison
parent ef07ed149d
commit 6f833cd3d7
2 changed files with 22 additions and 27 deletions

View File

@ -17,14 +17,13 @@ import (
"log"
"net/url"
"os"
"os/user"
"strconv"
"strings"
"time"
)
const gcsBaseUrl = "https://storage.googleapis.com"
const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
const googleCredentialsEnvVar = "GOOGLE_APPLICATION_CREDENTIALS"
func dataSourceGoogleSignedUrl() *schema.Resource {
return &schema.Resource{
@ -132,14 +131,14 @@ func dataSourceGoogleSignedUrlRead(d *schema.ResourceData, meta interface{}) err
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Construct URL
finalUrl := urlData.BuildUrl()
d.SetId(finalUrl)
d.SetId(urlData.EncodedSignature())
d.Set("signed_url", finalUrl)
return nil
}
// This looks for credentials json in the following places,
// preferring the first location found:
// in order of preference:
//
// 1. Credentials provided in data source `credentials` attribute.
// 2. Credentials provided in the provider definition.
@ -150,15 +149,15 @@ func loadJwtConfig(d *schema.ResourceData, meta interface{}) (*jwt.Config, error
credentials := ""
if v, ok := d.GetOk("credentials"); ok {
log.Println("[DEBUG] using data source credentials")
log.Println("[DEBUG] using data source credentials to sign URL")
credentials = v.(string)
} else if config.Credentials != "" {
log.Println("[DEBUG] using provider credentials")
log.Println("[DEBUG] using provider credentials to sign URL")
credentials = config.Credentials
} else if filename := os.Getenv(envVar); filename != "" {
log.Println("[DEBUG] using env GOOGLE_APPLICATION_CREDENTIALS credentials")
} else if filename := os.Getenv(googleCredentialsEnvVar); filename != "" {
log.Println("[DEBUG] using env GOOGLE_APPLICATION_CREDENTIALS credentials to sign URL")
credentials = filename
}
@ -179,14 +178,6 @@ func loadJwtConfig(d *schema.ResourceData, meta interface{}) (*jwt.Config, error
return nil, fmt.Errorf("Credentials not found in datasource, provider configuration or GOOGLE_APPLICATION_CREDENTIALS environment variable.")
}
func guessUnixHomeDir() string {
usr, err := user.Current()
if err == nil {
return usr.HomeDir
}
return os.Getenv("HOME")
}
// parsePrivateKey converts the binary contents of a private key file
// to an *rsa.PrivateKey. It detects whether the private key is in a
// PEM container or not. If so, it extracts the the private key
@ -258,13 +249,18 @@ func (u *UrlData) CreateSigningString() []byte {
return buf.Bytes()
}
// Builds the final signed URL a client can use to retrieve storage object
func (u *UrlData) BuildUrl() string {
func (u *UrlData) EncodedSignature() string {
// base64 encode signature
encoded := base64.StdEncoding.EncodeToString(u.Signature)
// encoded signature may include /, = characters that need escaping
encoded = url.QueryEscape(encoded)
return encoded
}
// Builds the final signed URL a client can use to retrieve storage object
func (u *UrlData) BuildUrl() string {
// set url
// https://cloud.google.com/storage/docs/access-control/create-signed-urls-program
var urlBuffer bytes.Buffer
@ -275,7 +271,7 @@ func (u *UrlData) BuildUrl() string {
urlBuffer.WriteString("&Expires=")
urlBuffer.WriteString(strconv.Itoa(u.Expires))
urlBuffer.WriteString("&Signature=")
urlBuffer.WriteString(encoded)
urlBuffer.WriteString(u.EncodedSignature())
return urlBuffer.String()
}

View File

@ -6,12 +6,12 @@ import (
"bytes"
"encoding/base64"
"fmt"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
"golang.org/x/oauth2/google"
"io/ioutil"
"net/http"
"net/url"
)
@ -31,8 +31,8 @@ const fakeCredentials = `{
// The following values are derived from the output of the `gsutil signurl` command.
// i.e.
// gsutil signurl fake_creds.json gs://tf-test-bucket-6159205297736845881/path/to/file
// URL HTTP Method Expiration Signed URL
// gs://tf-test-bucket-6159205297736845881/path/to/file GET 2016-08-12 14:03:30 https://storage.googleapis.com/tf-test-bucket-6159205297736845881/path/to/file?GoogleAccessId=user@gcp-project.iam.gserviceaccount.com&Expires=1470967410&Signature=JJvE2Jc%2BeoagyS1qRACKBGUkgLkKjw7cGymHhtB4IzzN3nbXDqr0acRWGy0%2BEpZ3HYNDalEYsK0lR9Q0WCgty5I0JKmPIuo9hOYa1xTNH%2B22xiWsekxGV%2FcA9FXgWpi%2BFt7fBmMk4dhDe%2BuuYc7N79hd0FYuSBNW1Wp32Bluoe4SNkNAB%2BuIDd9KqPzqs09UAbBoz2y4WxXOQnRyR8GAfb8B%2FDtv62gYjtmp%2F6%2Fyr6xj7byWKZdQt8kEftQLTQmP%2F17Efjp6p%2BXo71Q0F9IhAFiqWfp3Ij8hHDSebLcVb2ULXyHNNQpHBOhFgALrFW3I6Uc3WciLEOsBS9Ej3EGdTg%3D%3D
// URL HTTP Method Expiration Signed URL
// gs://tf-test-bucket-6159205297736845881/path/to/file GET 2016-08-12 14:03:30 https://storage.googleapis.com/tf-test-bucket-6159205297736845881/path/to/file?GoogleAccessId=user@gcp-project.iam.gserviceaccount.com&Expires=1470967410&Signature=JJvE2Jc%2BeoagyS1qRACKBGUkgLkKjw7cGymHhtB4IzzN3nbXDqr0acRWGy0%2BEpZ3HYNDalEYsK0lR9Q0WCgty5I0JKmPIuo9hOYa1xTNH%2B22xiWsekxGV%2FcA9FXgWpi%2BFt7fBmMk4dhDe%2BuuYc7N79hd0FYuSBNW1Wp32Bluoe4SNkNAB%2BuIDd9KqPzqs09UAbBoz2y4WxXOQnRyR8GAfb8B%2FDtv62gYjtmp%2F6%2Fyr6xj7byWKZdQt8kEftQLTQmP%2F17Efjp6p%2BXo71Q0F9IhAFiqWfp3Ij8hHDSebLcVb2ULXyHNNQpHBOhFgALrFW3I6Uc3WciLEOsBS9Ej3EGdTg%3D%3D
const testUrlPath = "/tf-test-bucket-6159205297736845881/path/to/file"
const testUrlExpires = 1470967410
@ -75,7 +75,7 @@ func TestUrlData_Signing(t *testing.T) {
}
func TestUrlData_CreateUrl(t *testing.T) {
func TestUrlData_BuildUrl(t *testing.T) {
// unescape and decode the expected signature
encodedSig, err := url.QueryUnescape(testUrlExpectedSignatureBase64Encoded)
if err != nil {
@ -107,7 +107,7 @@ func TestUrlData_CreateUrl(t *testing.T) {
func TestDatasourceSignedUrl_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
//PreCheck: func() { testAccPreCheck(t) },
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
@ -124,7 +124,7 @@ func TestDatasourceSignedUrl_accTest(t *testing.T) {
bucketName := fmt.Sprintf("tf-test-bucket-%d", acctest.RandInt())
resource.Test(t, resource.TestCase{
//PreCheck: func() { testAccPreCheck(t) },
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
resource.TestStep{
@ -163,12 +163,11 @@ func testAccGoogleSignedUrlRetrieval(n string) resource.TestCheckFunc {
url := a["signed_url"]
// send request to GET object using signed url
client := http.DefaultClient
client := cleanhttp.DefaultClient()
response, err := client.Get(url)
if err != nil {
return err
}
defer response.Body.Close()
body, err := ioutil.ReadAll(response.Body)
if err != nil {