Skip to content

Commit

Permalink
Ga secret manager (#3533) (#6432)
Browse files Browse the repository at this point in the history
* GA secret manager

* Fixing some issues with ga version

* GA datasource as well

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored May 20, 2020
1 parent 3ffd1f2 commit b225f7a
Show file tree
Hide file tree
Showing 19 changed files with 2,442 additions and 5 deletions.
12 changes: 12 additions & 0 deletions .changelog/3533.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```release-note:new-resource
google_secret_manager_secret
```
```release-note:new-resource
google_secret_manager_secret_version
```
```release-note:new-resource
google_secret_manager_secret_iam_*
```
```release-note:new-datasource
google_secret_manager_secret_version
```
3 changes: 3 additions & 0 deletions google/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type Config struct {
RedisBasePath string
ResourceManagerBasePath string
RuntimeConfigBasePath string
SecretManagerBasePath string
SecurityCenterBasePath string
ServiceManagementBasePath string
ServiceUsageBasePath string
Expand Down Expand Up @@ -249,6 +250,7 @@ var PubsubDefaultBasePath = "https://pubsub.googleapis.com/v1/"
var RedisDefaultBasePath = "https://redis.googleapis.com/v1/"
var ResourceManagerDefaultBasePath = "https://cloudresourcemanager.googleapis.com/v1/"
var RuntimeConfigDefaultBasePath = "https://runtimeconfig.googleapis.com/v1beta1/"
var SecretManagerDefaultBasePath = "https://secretmanager.googleapis.com/v1/"
var SecurityCenterDefaultBasePath = "https://securitycenter.googleapis.com/v1/"
var ServiceManagementDefaultBasePath = "https://servicemanagement.googleapis.com/v1/"
var ServiceUsageDefaultBasePath = "https://serviceusage.googleapis.com/v1/"
Expand Down Expand Up @@ -762,6 +764,7 @@ func ConfigureBasePaths(c *Config) {
c.RedisBasePath = RedisDefaultBasePath
c.ResourceManagerBasePath = ResourceManagerDefaultBasePath
c.RuntimeConfigBasePath = RuntimeConfigDefaultBasePath
c.SecretManagerBasePath = SecretManagerDefaultBasePath
c.SecurityCenterBasePath = SecurityCenterDefaultBasePath
c.ServiceManagementBasePath = ServiceManagementDefaultBasePath
c.ServiceUsageBasePath = ServiceUsageDefaultBasePath
Expand Down
125 changes: 125 additions & 0 deletions google/data_source_secret_manager_secret_version.go
Original file line number Diff line number Diff line change
@@ -1 +1,126 @@
package google

import (
"encoding/base64"
"fmt"
"log"
"regexp"
"time"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func dataSourceSecretManagerSecretVersion() *schema.Resource {
return &schema.Resource{
Read: dataSourceSecretManagerSecretVersionRead,
Schema: map[string]*schema.Schema{
"project": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"secret": {
Type: schema.TypeString,
Required: true,
DiffSuppressFunc: compareSelfLinkOrResourceName,
},
"version": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"create_time": {
Type: schema.TypeString,
Computed: true,
},
"destroy_time": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"enabled": {
Type: schema.TypeBool,
Computed: true,
},
"secret_data": {
Type: schema.TypeString,
Computed: true,
Sensitive: true,
},
},
}
}

func dataSourceSecretManagerSecretVersionRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

fv, err := parseProjectFieldValue("secrets", d.Get("secret").(string), "project", d, config, false)
if err != nil {
return err
}
if d.Get("project").(string) != "" && d.Get("project").(string) != fv.Project {
return fmt.Errorf("The project set on this secret version (%s) is not equal to the project where this secret exists (%s).", d.Get("project").(string), fv.Project)
}
project := fv.Project
d.Set("project", project)
d.Set("secret", fv.Name)

var url string
versionNum := d.Get("version")

if versionNum != "" {
url, err = replaceVars(d, config, "{{SecretManagerBasePath}}projects/{{project}}/secrets/{{secret}}/versions/{{version}}")
if err != nil {
return err
}
} else {
url, err = replaceVars(d, config, "{{SecretManagerBasePath}}projects/{{project}}/secrets/{{secret}}/versions/latest")
if err != nil {
return err
}
}

var version map[string]interface{}
version, err = sendRequest(config, "GET", project, url, nil)
if err != nil {
return fmt.Errorf("Error retrieving available secret manager secret versions: %s", err.Error())
}

secretVersionRegex := regexp.MustCompile("projects/(.+)/secrets/(.+)/versions/(.+)$")

parts := secretVersionRegex.FindStringSubmatch(version["name"].(string))
// should return [full string, project number, secret name, version number]
if len(parts) != 4 {
panic(fmt.Sprintf("secret name, %s, does not match format, projects/{{project}}/secrets/{{secret}}/versions/{{version}}", version["name"].(string)))
}

log.Printf("[DEBUG] Received Google SecretManager Version: %q", version)

d.Set("version", parts[3])

url = fmt.Sprintf("%s:access", url)
resp, err := sendRequest(config, "GET", project, url, nil)
if err != nil {
return fmt.Errorf("Error retrieving available secret manager secret version access: %s", err.Error())
}

d.Set("create_time", version["createTime"].(string))
if version["destroyTime"] != nil {
d.Set("destroy_time", version["destroyTime"].(string))
}
d.Set("name", version["name"].(string))
d.Set("enabled", true)

data := resp["payload"].(map[string]interface{})
secretData, err := base64.StdEncoding.DecodeString(data["data"].(string))
if err != nil {
return fmt.Errorf("Error decoding secret manager secret version data: %s", err.Error())
}
d.Set("secret_data", string(secretData))

d.SetId(time.Now().UTC().String())
return nil
}
126 changes: 126 additions & 0 deletions google/data_source_secret_manager_secret_version_test.go
Original file line number Diff line number Diff line change
@@ -1 +1,127 @@
package google

import (
"errors"
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
)

func TestAccDatasourceSecretManagerSecretVersion_basic(t *testing.T) {
t.Parallel()

randomString := randString(t, 10)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecretManagerSecretVersionDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDatasourceSecretManagerSecretVersion_basic(randomString),
Check: resource.ComposeTestCheckFunc(
testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version.basic", "1"),
),
},
},
})
}

func TestAccDatasourceSecretManagerSecretVersion_latest(t *testing.T) {
t.Parallel()

randomString := randString(t, 10)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckSecretManagerSecretVersionDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDatasourceSecretManagerSecretVersion_latest(randomString),
Check: resource.ComposeTestCheckFunc(
testAccCheckDatasourceSecretManagerSecretVersion("data.google_secret_manager_secret_version.latest", "2"),
),
},
},
})
}

func testAccCheckDatasourceSecretManagerSecretVersion(n, expected string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Can't find Secret Version data source: %s", n)
}

if rs.Primary.ID == "" {
return errors.New("data source ID not set.")
}

version, ok := rs.Primary.Attributes["version"]
if !ok {
return errors.New("can't find 'version' attribute")
}

if version != expected {
return fmt.Errorf("expected %s, got %s, version not found", expected, version)
}
return nil
}
}

func testAccDatasourceSecretManagerSecretVersion_latest(randomString string) string {
return fmt.Sprintf(`
resource "google_secret_manager_secret" "secret-basic" {
secret_id = "tf-test-secret-version-%s"
labels = {
label = "my-label"
}
replication {
automatic = true
}
}
resource "google_secret_manager_secret_version" "secret-version-basic-1" {
secret = google_secret_manager_secret.secret-basic.name
secret_data = "my-tf-test-secret-first"
}
resource "google_secret_manager_secret_version" "secret-version-basic-2" {
secret = google_secret_manager_secret.secret-basic.name
secret_data = "my-tf-test-secret-second"
depends_on = [google_secret_manager_secret_version.secret-version-basic-1]
}
data "google_secret_manager_secret_version" "latest" {
secret = google_secret_manager_secret_version.secret-version-basic-2.secret
}
`, randomString)
}

func testAccDatasourceSecretManagerSecretVersion_basic(randomString string) string {
return fmt.Sprintf(`
resource "google_secret_manager_secret" "secret-basic" {
secret_id = "tf-test-secret-version-%s"
labels = {
label = "my-label"
}
replication {
automatic = true
}
}
resource "google_secret_manager_secret_version" "secret-version-basic" {
secret = google_secret_manager_secret.secret-basic.name
secret_data = "my-tf-test-secret-%s"
}
data "google_secret_manager_secret_version" "basic" {
secret = google_secret_manager_secret_version.secret-version-basic.secret
version = 1
}
`, randomString, randomString)
}
Loading

0 comments on commit b225f7a

Please sign in to comment.