Skip to content

Commit

Permalink
Adds storage_hmac_key_resource (#3084)
Browse files Browse the repository at this point in the history
* Adds hmac key

* Fixes up hmacKey resource properties in terraform

* Update products/storage/terraform.yaml

Co-Authored-By: Riley Karson <[email protected]>

* Update products/storage/api.yaml

Co-Authored-By: Riley Karson <[email protected]>

* Adds an example, website links, and several fixes from review

* Adds test and fixes hmac_key id

* tweaking hmac_key example

* Update third_party/terraform/tests/resource_storage_hmac_key_test.go

Co-Authored-By: Riley Karson <[email protected]>

* Update products/storage/api.yaml

Co-Authored-By: Riley Karson <[email protected]>

* Update third_party/terraform/tests/resource_storage_hmac_key_test.go

Co-Authored-By: Riley Karson <[email protected]>

* hmac_key: adds doc warning about secrets, fixes yaml formatting, and improves test

* More fixes for review

* Fixing gofmt

* fix resource name

* more iteration

* More fixes

* RM unused var in hmac_key_test

* hmac_key: Pre-delete and more fixes

* Fixing wrong assumptions

* Edits to support read schema

* Get tests passing, handle deleted items properly

* Sidebar - to _

* Remove the update encoder because the docs are wrong on update format anyways

Co-authored-by: Riley Karson <[email protected]>
  • Loading branch information
geojaz and rileykarson authored Feb 13, 2020
1 parent abcd9f9 commit 6bf6455
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 2 deletions.
2 changes: 2 additions & 0 deletions products/storage/ansible.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ overrides: !ruby/object:Overrides::ResourceOverrides
exclude: true
Object: !ruby/object:Overrides::Ansible::ResourceOverride
exclude: true
HmacKey: !ruby/object:Overrides::Ansible::ResourceOverride
exclude: true
files: !ruby/object:Provider::Config::Files
resource:
<%= lines(indent(compile('provider/ansible/resource~compile.yaml'), 4)) -%>
61 changes: 60 additions & 1 deletion products/storage/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -780,4 +780,63 @@ objects:
name: timeUpdated
api_name: updated
description: The modification time of the object metadata.

- !ruby/object:Api::Resource
name: 'HmacKey'
kind: 'storage#hmacKey'
base_url: projects/{{project}}/hmacKeys
create_url: projects/{{project}}/hmacKeys?serviceAccountEmail={{serviceAccountEmail}}
self_link: projects/{{project}}/hmacKeys/{{accessId}}
# technically updatable, but implemented as custom update for new fingerprint support
input: true
references: !ruby/object:Api::Resource::ReferenceLinks
guides:
'Official Documentation': 'https://cloud.google.com/storage/docs/authentication/managing-hmackeys'
api: 'https://cloud.google.com/storage/docs/json_api/v1/projects/hmacKeys'
description: |
The hmacKeys resource represents an HMAC key within Cloud Storage. The resource
consists of a secret and HMAC key metadata. HMAC keys can be used as credentials
for service accounts.
properties:
- !ruby/object:Api::Type::String
name: 'serviceAccountEmail'
description: |
The email address of the key's associated service account.
required: true
- !ruby/object:Api::Type::Enum
name: 'state'
description: |
The state of the key. Can be set to one of ACTIVE, INACTIVE.
default_value: :ACTIVE
values:
- :ACTIVE
- :INACTIVE
# - :DELETED (not directly settable)
update_verb: :PUT
update_url: projects/{{project}}/hmacKeys/{{accessId}}
update_id: 'state'
fingerprint_name: 'etag'
- !ruby/object:Api::Type::String
name: 'secret'
output: true
description: |
HMAC secret key material.
- !ruby/object:Api::Type::String
name: 'accessId'
output: true
description: |
The access ID of the HMAC Key.
- !ruby/object:Api::Type::String
name: 'id'
output: true
description: |
The ID of the HMAC key, including the Project ID and the Access ID.
- !ruby/object:Api::Type::Time
name: 'timeCreated'
output: true
description: |
'The creation time of the HMAC key in RFC 3339 format. '
- !ruby/object:Api::Type::Time
name: 'updated'
output: true
description: |
'The last modification time of the HMAC key metadata in RFC 3339 format.'
4 changes: 3 additions & 1 deletion products/storage/inspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,6 @@ overrides: !ruby/object:Overrides::ResourceOverrides
timeCreated: !ruby/object:Overrides::Inspec::PropertyOverride
override_name: object_created_times
bucket: !ruby/object:Overrides::Inspec::PropertyOverride
override_name: object_bucket
override_name: object_bucket
HmacKey: !ruby/object:Overrides::Inspec::ResourceOverride
exclude: true
31 changes: 31 additions & 0 deletions products/storage/terraform.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,37 @@ overrides: !ruby/object:Overrides::ResourceOverrides
ignore_read: true
Object: !ruby/object:Overrides::Terraform::ResourceOverride
exclude: true
HmacKey: !ruby/object:Overrides::Terraform::ResourceOverride
create_url: projects/{{project}}/hmacKeys?serviceAccountEmail={{service_account_email}}
self_link: projects/{{project}}/hmacKeys/{{access_id}}
id_format: "projects/{{project}}/hmacKeys/{{access_id}}"
import_format: ['projects/{{project}}/hmacKeys/{{access_id}}']
# This resource does not have a name field
skip_sweeper: true
examples:
- !ruby/object:Provider::Terraform::Examples
name: "storage_hmac_key"
primary_resource_id: "key"
vars:
account_id: "my-svc-acc"
docs: !ruby/object:Provider::Terraform::Docs
warning: |
All arguments including the `secret` value will be stored in the raw
state as plain-text. [Read more about sensitive data in state](/docs/state/sensitive-data.html).
On import, the `secret` value will not be retrieved.
properties:
id: !ruby/object:Overrides::Terraform::PropertyOverride
exclude: true
secret: !ruby/object:Overrides::Terraform::PropertyOverride
ignore_read: true
sensitive: true
state: !ruby/object:Overrides::Terraform::PropertyOverride
update_url: projects/{{project}}/hmacKeys/{{access_id}}
custom_code: !ruby/object:Provider::Terraform::CustomCode
decoder: templates/terraform/decoders/storage_hmac_key.go.erb
pre_delete: templates/terraform/pre_delete/storage_hmac_key.go.erb
post_create: templates/terraform/post_create/storage_hmac_key.go.erb
test_check_destroy: templates/terraform/custom_check_destroy/storage_hmac_key.go.erb
# This is for copying files over
files: !ruby/object:Provider::Config::Files
# These files have templating (ERB) code that will be run.
Expand Down
17 changes: 17 additions & 0 deletions templates/terraform/custom_check_destroy/storage_hmac_key.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
config := testAccProvider.Meta().(*Config)

url, err := replaceVarsForTest(config, rs, "{{StorageBasePath}}projects/{{project}}/hmacKeys/{{access_id}}")
if err != nil {
return err
}

res, err := sendRequest(config, "GET", "", url, nil)
if err != nil {
return nil
}

if v := res["state"]; v == "DELETED" {
return nil
}

return fmt.Errorf("StorageHmacKey still exists at %s", url)
5 changes: 5 additions & 0 deletions templates/terraform/decoders/storage_hmac_key.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
if v := res["state"]; v == "DELETED" {
return nil, nil
}

return res, nil
7 changes: 7 additions & 0 deletions templates/terraform/examples/storage_hmac_key.tf.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "google_service_account" "service_account" {
account_id = "<%= ctx[:vars]['account_id'] %>"
}

resource "google_storage_hmac_key" "<%= ctx[:primary_resource_id] %>" {
service_account_email = google_service_account.service_account.email
}
23 changes: 23 additions & 0 deletions templates/terraform/post_create/storage_hmac_key.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// `secret` and `access_id` are generated by the API upon successful CREATE. The following
// ensures terraform has the correct values based on the Projects.hmacKeys response object.
secret, ok := res["secret"].(string)
if !ok {
return fmt.Errorf("The response to CREATE was missing an expected field. Your create did not work.")
}

d.Set("secret", secret)

metadata := res["metadata"].(map[string]interface{})
accessId, ok := metadata["accessId"].(string)
if !ok {
return fmt.Errorf("The response to CREATE was missing an expected field. Your create did not work.")
}

d.Set("access_id", accessId)

id, err = replaceVars(d, config, "projects/{{project}}/hmacKeys/{{access_id}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}

d.SetId(id)
26 changes: 26 additions & 0 deletions templates/terraform/pre_delete/storage_hmac_key.go.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
getUrl, err := replaceVars(d, config, "{{StorageBasePath}}projects/{{project}}/hmacKeys/{{access_id}}")
if err != nil {
return err
}

getRes, err := sendRequest(config, "GET", project, getUrl, nil)
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("StorageHmacKey %q", d.Id()))
}

// HmacKeys need to be INACTIVE to be deleted and the API doesn't accept noop
// updates
if v := getRes["state"]; v == "ACTIVE" {
getRes["state"] = "INACTIVE"
updateUrl, err := replaceVars(d, config, "{{StorageBasePath}}projects/{{project}}/hmacKeys/{{access_id}}")
if err != nil {
return err
}

log.Printf("[DEBUG] Deactivating HmacKey %q: %#v", d.Id(), getRes)
_, err = sendRequestWithTimeout(config, "PUT", project, updateUrl, getRes, d.Timeout(schema.TimeoutUpdate))
if err != nil {
return fmt.Errorf("Error deactivating HmacKey %q: %s", d.Id(), err)
}
}

53 changes: 53 additions & 0 deletions third_party/terraform/tests/resource_storage_hmac_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package google

import (
"fmt"
"testing"

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

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

saName := fmt.Sprintf("%v%v", "service-account", acctest.RandString(10))
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckStorageHmacKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccGoogleStorageHmacKeyBasic(saName, "ACTIVE"),
},
{
ResourceName: "google_storage_hmac_key.key",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"secret"},
},
{
Config: testAccGoogleStorageHmacKeyBasic(saName, "INACTIVE"),
},
{
ResourceName: "google_storage_hmac_key.key",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"secret"},
},
},
})
}

func testAccGoogleStorageHmacKeyBasic(saName, state string) string {
return fmt.Sprintf(`
resource "google_service_account" "service_account" {
account_id = "%s"
}
resource "google_storage_hmac_key" "key" {
service_account_email = google_service_account.service_account.email
state = "%s"
}
`, saName, state)
}
4 changes: 4 additions & 0 deletions third_party/terraform/website-compiled/google.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,10 @@
<a href="/docs/providers/google/r/storage_default_object_acl.html">google_storage_default_object_acl</a>
</li>

<li<%%= sidebar_current("docs-google-storage-hmac-key") %>>
<a href="/docs/providers/google/r/storage_hmac_key.html">google_storage_hmac_key</a>
</li>

<li<%%= sidebar_current("docs-google-storage-notification") %>>
<a href="/docs/providers/google/r/storage_notification.html">google_storage_notification</a>
</li>
Expand Down

0 comments on commit 6bf6455

Please sign in to comment.