| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| // ---------------------------------------------------------------------------- |
| // |
| // *** AUTO GENERATED CODE *** Type: MMv1 *** |
| // |
| // ---------------------------------------------------------------------------- |
| // |
| // This file is automatically generated by Magic Modules and manual |
| // changes will be clobbered when the file is regenerated. |
| // |
| // Please read more about how to change this file in |
| // .github/CONTRIBUTING.md. |
| // |
| // ---------------------------------------------------------------------------- |
| |
| package kms |
| |
| import ( |
| "context" |
| "fmt" |
| "log" |
| "net/http" |
| "reflect" |
| "regexp" |
| "strings" |
| "time" |
| |
| "github.com/hashicorp/terraform-plugin-sdk/v2/helper/customdiff" |
| "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" |
| |
| "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" |
| transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" |
| "github.com/hashicorp/terraform-provider-google-beta/google-beta/verify" |
| ) |
| |
| func ResourceKMSCryptoKey() *schema.Resource { |
| return &schema.Resource{ |
| Create: resourceKMSCryptoKeyCreate, |
| Read: resourceKMSCryptoKeyRead, |
| Update: resourceKMSCryptoKeyUpdate, |
| Delete: resourceKMSCryptoKeyDelete, |
| |
| Importer: &schema.ResourceImporter{ |
| State: resourceKMSCryptoKeyImport, |
| }, |
| |
| Timeouts: &schema.ResourceTimeout{ |
| Create: schema.DefaultTimeout(20 * time.Minute), |
| Update: schema.DefaultTimeout(20 * time.Minute), |
| Delete: schema.DefaultTimeout(20 * time.Minute), |
| }, |
| |
| SchemaVersion: 1, |
| |
| StateUpgraders: []schema.StateUpgrader{ |
| { |
| Type: resourceKMSCryptoKeyResourceV0().CoreConfigSchema().ImpliedType(), |
| Upgrade: ResourceKMSCryptoKeyUpgradeV0, |
| Version: 0, |
| }, |
| }, |
| CustomizeDiff: customdiff.All( |
| tpgresource.SetLabelsDiff, |
| ), |
| |
| Schema: map[string]*schema.Schema{ |
| "key_ring": { |
| Type: schema.TypeString, |
| Required: true, |
| ForceNew: true, |
| DiffSuppressFunc: kmsCryptoKeyRingsEquivalent, |
| Description: `The KeyRing that this key belongs to. |
| Format: ''projects/{{project}}/locations/{{location}}/keyRings/{{keyRing}}''.`, |
| }, |
| "name": { |
| Type: schema.TypeString, |
| Required: true, |
| ForceNew: true, |
| Description: `The resource name for the CryptoKey.`, |
| }, |
| "crypto_key_backend": { |
| Type: schema.TypeString, |
| Computed: true, |
| Optional: true, |
| ForceNew: true, |
| Description: `The resource name of the backend environment associated with all CryptoKeyVersions within this CryptoKey. |
| The resource name is in the format "projects/*/locations/*/ekmConnections/*" and only applies to "EXTERNAL_VPC" keys.`, |
| }, |
| "destroy_scheduled_duration": { |
| Type: schema.TypeString, |
| Computed: true, |
| Optional: true, |
| ForceNew: true, |
| Description: `The period of time that versions of this key spend in the DESTROY_SCHEDULED state before transitioning to DESTROYED. |
| If not specified at creation time, the default duration is 30 days.`, |
| }, |
| "import_only": { |
| Type: schema.TypeBool, |
| Computed: true, |
| Optional: true, |
| ForceNew: true, |
| Description: `Whether this key may contain imported versions only.`, |
| }, |
| "key_access_justifications_policy": { |
| Type: schema.TypeList, |
| Computed: true, |
| Optional: true, |
| Description: `The policy used for Key Access Justifications Policy Enforcement. If this |
| field is present and this key is enrolled in Key Access Justifications |
| Policy Enforcement, the policy will be evaluated in encrypt, decrypt, and |
| sign operations, and the operation will fail if rejected by the policy. The |
| policy is defined by specifying zero or more allowed justification codes. |
| https://cloud.google.com/assured-workloads/key-access-justifications/docs/justification-codes |
| By default, this field is absent, and all justification codes are allowed. |
| This field is currently in beta and is subject to change.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "allowed_access_reasons": { |
| Type: schema.TypeList, |
| Optional: true, |
| Description: `The list of allowed reasons for access to this CryptoKey. Zero allowed |
| access reasons means all encrypt, decrypt, and sign operations for |
| this CryptoKey will fail.`, |
| Elem: &schema.Schema{ |
| Type: schema.TypeString, |
| }, |
| }, |
| }, |
| }, |
| }, |
| "labels": { |
| Type: schema.TypeMap, |
| Optional: true, |
| Description: `Labels with user-defined metadata to apply to this resource. |
| |
| |
| **Note**: This field is non-authoritative, and will only manage the labels present in your configuration. |
| Please refer to the field 'effective_labels' for all of the labels present on the resource.`, |
| Elem: &schema.Schema{Type: schema.TypeString}, |
| }, |
| "purpose": { |
| Type: schema.TypeString, |
| Optional: true, |
| ForceNew: true, |
| Description: `The immutable purpose of this CryptoKey. See the |
| [purpose reference](https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys#CryptoKeyPurpose) |
| for possible inputs. |
| Default value is "ENCRYPT_DECRYPT".`, |
| Default: "ENCRYPT_DECRYPT", |
| }, |
| "rotation_period": { |
| Type: schema.TypeString, |
| Optional: true, |
| ValidateFunc: verify.OrEmpty(validateKmsCryptoKeyRotationPeriod), |
| Description: `Every time this period passes, generate a new CryptoKeyVersion and set it as the primary. |
| The first rotation will take place after the specified period. The rotation period has |
| the format of a decimal number with up to 9 fractional digits, followed by the |
| letter 's' (seconds). It must be greater than a day (ie, 86400).`, |
| }, |
| "skip_initial_version_creation": { |
| Type: schema.TypeBool, |
| Optional: true, |
| ForceNew: true, |
| Description: `If set to true, the request will create a CryptoKey without any CryptoKeyVersions. |
| You must use the 'google_kms_crypto_key_version' resource to create a new CryptoKeyVersion |
| or 'google_kms_key_ring_import_job' resource to import the CryptoKeyVersion.`, |
| }, |
| "version_template": { |
| Type: schema.TypeList, |
| Computed: true, |
| Optional: true, |
| Description: `A template describing settings for new crypto key versions.`, |
| MaxItems: 1, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "algorithm": { |
| Type: schema.TypeString, |
| Required: true, |
| Description: `The algorithm to use when creating a version based on this template. |
| See the [algorithm reference](https://cloud.google.com/kms/docs/reference/rest/v1/CryptoKeyVersionAlgorithm) for possible inputs.`, |
| }, |
| "protection_level": { |
| Type: schema.TypeString, |
| Optional: true, |
| ForceNew: true, |
| Description: `The protection level to use when creating a version based on this template. Possible values include "SOFTWARE", "HSM", "EXTERNAL", "EXTERNAL_VPC". Defaults to "SOFTWARE".`, |
| Default: "SOFTWARE", |
| }, |
| }, |
| }, |
| }, |
| "effective_labels": { |
| Type: schema.TypeMap, |
| Computed: true, |
| Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`, |
| Elem: &schema.Schema{Type: schema.TypeString}, |
| }, |
| "primary": { |
| Type: schema.TypeList, |
| Computed: true, |
| Description: `A copy of the primary CryptoKeyVersion that will be used by cryptoKeys.encrypt when this CryptoKey is given in EncryptRequest.name. |
| Keys with purpose ENCRYPT_DECRYPT may have a primary. For other keys, this field will be unset.`, |
| Elem: &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "name": { |
| Type: schema.TypeString, |
| Computed: true, |
| Description: `The resource name for this CryptoKeyVersion.`, |
| }, |
| "state": { |
| Type: schema.TypeString, |
| Computed: true, |
| Description: `The current state of the CryptoKeyVersion.`, |
| }, |
| }, |
| }, |
| }, |
| "terraform_labels": { |
| Type: schema.TypeMap, |
| Computed: true, |
| Description: `The combination of labels configured directly on the resource |
| and default labels configured on the provider.`, |
| Elem: &schema.Schema{Type: schema.TypeString}, |
| }, |
| }, |
| UseJSONNumber: true, |
| } |
| } |
| |
| func resourceKMSCryptoKeyCreate(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| obj := make(map[string]interface{}) |
| purposeProp, err := expandKMSCryptoKeyPurpose(d.Get("purpose"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("purpose"); !tpgresource.IsEmptyValue(reflect.ValueOf(purposeProp)) && (ok || !reflect.DeepEqual(v, purposeProp)) { |
| obj["purpose"] = purposeProp |
| } |
| rotationPeriodProp, err := expandKMSCryptoKeyRotationPeriod(d.Get("rotation_period"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("rotation_period"); !tpgresource.IsEmptyValue(reflect.ValueOf(rotationPeriodProp)) && (ok || !reflect.DeepEqual(v, rotationPeriodProp)) { |
| obj["rotationPeriod"] = rotationPeriodProp |
| } |
| versionTemplateProp, err := expandKMSCryptoKeyVersionTemplate(d.Get("version_template"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("version_template"); !tpgresource.IsEmptyValue(reflect.ValueOf(versionTemplateProp)) && (ok || !reflect.DeepEqual(v, versionTemplateProp)) { |
| obj["versionTemplate"] = versionTemplateProp |
| } |
| destroyScheduledDurationProp, err := expandKMSCryptoKeyDestroyScheduledDuration(d.Get("destroy_scheduled_duration"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("destroy_scheduled_duration"); !tpgresource.IsEmptyValue(reflect.ValueOf(destroyScheduledDurationProp)) && (ok || !reflect.DeepEqual(v, destroyScheduledDurationProp)) { |
| obj["destroyScheduledDuration"] = destroyScheduledDurationProp |
| } |
| importOnlyProp, err := expandKMSCryptoKeyImportOnly(d.Get("import_only"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("import_only"); !tpgresource.IsEmptyValue(reflect.ValueOf(importOnlyProp)) && (ok || !reflect.DeepEqual(v, importOnlyProp)) { |
| obj["importOnly"] = importOnlyProp |
| } |
| cryptoKeyBackendProp, err := expandKMSCryptoKeyCryptoKeyBackend(d.Get("crypto_key_backend"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("crypto_key_backend"); !tpgresource.IsEmptyValue(reflect.ValueOf(cryptoKeyBackendProp)) && (ok || !reflect.DeepEqual(v, cryptoKeyBackendProp)) { |
| obj["cryptoKeyBackend"] = cryptoKeyBackendProp |
| } |
| keyAccessJustificationsPolicyProp, err := expandKMSCryptoKeyKeyAccessJustificationsPolicy(d.Get("key_access_justifications_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("key_access_justifications_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(keyAccessJustificationsPolicyProp)) && (ok || !reflect.DeepEqual(v, keyAccessJustificationsPolicyProp)) { |
| obj["keyAccessJustificationsPolicy"] = keyAccessJustificationsPolicyProp |
| } |
| labelsProp, err := expandKMSCryptoKeyEffectiveLabels(d.Get("effective_labels"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(labelsProp)) && (ok || !reflect.DeepEqual(v, labelsProp)) { |
| obj["labels"] = labelsProp |
| } |
| |
| obj, err = resourceKMSCryptoKeyEncoder(d, meta, obj) |
| if err != nil { |
| return err |
| } |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{KMSBasePath}}{{key_ring}}/cryptoKeys?cryptoKeyId={{name}}&skipInitialVersionCreation={{skip_initial_version_creation}}") |
| if err != nil { |
| return err |
| } |
| |
| log.Printf("[DEBUG] Creating new CryptoKey: %#v", obj) |
| billingProject := "" |
| |
| if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { |
| billingProject = parts[1] |
| } |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| headers := make(http.Header) |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "POST", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Body: obj, |
| Timeout: d.Timeout(schema.TimeoutCreate), |
| Headers: headers, |
| }) |
| if err != nil { |
| return fmt.Errorf("Error creating CryptoKey: %s", err) |
| } |
| |
| // Store the ID now |
| id, err := tpgresource.ReplaceVars(d, config, "{{key_ring}}/cryptoKeys/{{name}}") |
| if err != nil { |
| return fmt.Errorf("Error constructing id: %s", err) |
| } |
| d.SetId(id) |
| |
| log.Printf("[DEBUG] Finished creating CryptoKey %q: %#v", d.Id(), res) |
| |
| return resourceKMSCryptoKeyRead(d, meta) |
| } |
| |
| func resourceKMSCryptoKeyRead(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{KMSBasePath}}{{key_ring}}/cryptoKeys/{{name}}") |
| if err != nil { |
| return err |
| } |
| |
| billingProject := "" |
| |
| if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { |
| billingProject = parts[1] |
| } |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| headers := make(http.Header) |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "GET", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Headers: headers, |
| }) |
| if err != nil { |
| return transport_tpg.HandleNotFoundError(err, d, fmt.Sprintf("KMSCryptoKey %q", d.Id())) |
| } |
| |
| res, err = resourceKMSCryptoKeyDecoder(d, meta, res) |
| if err != nil { |
| return err |
| } |
| |
| if res == nil { |
| // Decoding the object has resulted in it being gone. It may be marked deleted |
| log.Printf("[DEBUG] Removing KMSCryptoKey because it no longer exists.") |
| d.SetId("") |
| return nil |
| } |
| |
| if err := d.Set("labels", flattenKMSCryptoKeyLabels(res["labels"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("primary", flattenKMSCryptoKeyPrimary(res["primary"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("purpose", flattenKMSCryptoKeyPurpose(res["purpose"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("rotation_period", flattenKMSCryptoKeyRotationPeriod(res["rotationPeriod"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("version_template", flattenKMSCryptoKeyVersionTemplate(res["versionTemplate"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("destroy_scheduled_duration", flattenKMSCryptoKeyDestroyScheduledDuration(res["destroyScheduledDuration"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("import_only", flattenKMSCryptoKeyImportOnly(res["importOnly"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("crypto_key_backend", flattenKMSCryptoKeyCryptoKeyBackend(res["cryptoKeyBackend"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("key_access_justifications_policy", flattenKMSCryptoKeyKeyAccessJustificationsPolicy(res["keyAccessJustificationsPolicy"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("terraform_labels", flattenKMSCryptoKeyTerraformLabels(res["labels"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| if err := d.Set("effective_labels", flattenKMSCryptoKeyEffectiveLabels(res["labels"], d, config)); err != nil { |
| return fmt.Errorf("Error reading CryptoKey: %s", err) |
| } |
| |
| return nil |
| } |
| |
| func resourceKMSCryptoKeyUpdate(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| billingProject := "" |
| |
| obj := make(map[string]interface{}) |
| rotationPeriodProp, err := expandKMSCryptoKeyRotationPeriod(d.Get("rotation_period"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("rotation_period"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, rotationPeriodProp)) { |
| obj["rotationPeriod"] = rotationPeriodProp |
| } |
| versionTemplateProp, err := expandKMSCryptoKeyVersionTemplate(d.Get("version_template"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("version_template"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, versionTemplateProp)) { |
| obj["versionTemplate"] = versionTemplateProp |
| } |
| keyAccessJustificationsPolicyProp, err := expandKMSCryptoKeyKeyAccessJustificationsPolicy(d.Get("key_access_justifications_policy"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("key_access_justifications_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, keyAccessJustificationsPolicyProp)) { |
| obj["keyAccessJustificationsPolicy"] = keyAccessJustificationsPolicyProp |
| } |
| labelsProp, err := expandKMSCryptoKeyEffectiveLabels(d.Get("effective_labels"), d, config) |
| if err != nil { |
| return err |
| } else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) { |
| obj["labels"] = labelsProp |
| } |
| |
| obj, err = resourceKMSCryptoKeyUpdateEncoder(d, meta, obj) |
| if err != nil { |
| return err |
| } |
| |
| url, err := tpgresource.ReplaceVars(d, config, "{{KMSBasePath}}{{key_ring}}/cryptoKeys/{{name}}") |
| if err != nil { |
| return err |
| } |
| |
| log.Printf("[DEBUG] Updating CryptoKey %q: %#v", d.Id(), obj) |
| headers := make(http.Header) |
| updateMask := []string{} |
| |
| if d.HasChange("rotation_period") { |
| updateMask = append(updateMask, "rotationPeriod", |
| "nextRotationTime") |
| } |
| |
| if d.HasChange("version_template") { |
| updateMask = append(updateMask, "versionTemplate.algorithm") |
| } |
| |
| if d.HasChange("key_access_justifications_policy") { |
| updateMask = append(updateMask, "keyAccessJustificationsPolicy") |
| } |
| |
| if d.HasChange("effective_labels") { |
| updateMask = append(updateMask, "labels") |
| } |
| // updateMask is a URL parameter but not present in the schema, so ReplaceVars |
| // won't set it |
| url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) |
| if err != nil { |
| return err |
| } |
| if parts := regexp.MustCompile(`projects\/([^\/]+)\/`).FindStringSubmatch(url); parts != nil { |
| billingProject = parts[1] |
| } |
| |
| // err == nil indicates that the billing_project value was found |
| if bp, err := tpgresource.GetBillingProject(d, config); err == nil { |
| billingProject = bp |
| } |
| |
| // if updateMask is empty we are not updating anything so skip the post |
| if len(updateMask) > 0 { |
| res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| Config: config, |
| Method: "PATCH", |
| Project: billingProject, |
| RawURL: url, |
| UserAgent: userAgent, |
| Body: obj, |
| Timeout: d.Timeout(schema.TimeoutUpdate), |
| Headers: headers, |
| }) |
| |
| if err != nil { |
| return fmt.Errorf("Error updating CryptoKey %q: %s", d.Id(), err) |
| } else { |
| log.Printf("[DEBUG] Finished updating CryptoKey %q: %#v", d.Id(), res) |
| } |
| |
| } |
| |
| return resourceKMSCryptoKeyRead(d, meta) |
| } |
| |
| func resourceKMSCryptoKeyDelete(d *schema.ResourceData, meta interface{}) error { |
| config := meta.(*transport_tpg.Config) |
| userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent) |
| if err != nil { |
| return err |
| } |
| |
| cryptoKeyId, err := ParseKmsCryptoKeyId(d.Id(), config) |
| if err != nil { |
| return err |
| } |
| |
| log.Printf(` |
| [WARNING] KMS CryptoKey resources cannot be deleted from GCP. The CryptoKey %s will be removed from Terraform state, |
| and all its CryptoKeyVersions will be destroyed, but it will still be present in the project.`, cryptoKeyId.CryptoKeyId()) |
| |
| // Delete all versions of the key |
| if err := clearCryptoKeyVersions(cryptoKeyId, userAgent, config); err != nil { |
| return err |
| } |
| |
| // Make sure automatic key rotation is disabled if set |
| if d.Get("rotation_period") != "" { |
| if err := disableCryptoKeyRotation(cryptoKeyId, userAgent, config); err != nil { |
| return fmt.Errorf( |
| "While cryptoKeyVersions were cleared, Terraform was unable to disable automatic rotation of key due to an error: %s."+ |
| "Please retry or manually disable automatic rotation to prevent creation of a new version of this key.", err) |
| } |
| } |
| |
| d.SetId("") |
| return nil |
| } |
| |
| func resourceKMSCryptoKeyImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { |
| |
| config := meta.(*transport_tpg.Config) |
| |
| cryptoKeyId, err := ParseKmsCryptoKeyId(d.Id(), config) |
| if err != nil { |
| return nil, err |
| } |
| |
| if err := d.Set("key_ring", cryptoKeyId.KeyRingId.KeyRingId()); err != nil { |
| return nil, fmt.Errorf("Error setting key_ring: %s", err) |
| } |
| if err := d.Set("name", cryptoKeyId.Name); err != nil { |
| return nil, fmt.Errorf("Error setting name: %s", err) |
| } |
| |
| if err := d.Set("skip_initial_version_creation", false); err != nil { |
| return nil, fmt.Errorf("Error setting skip_initial_version_creation: %s", err) |
| } |
| |
| id, err := tpgresource.ReplaceVars(d, config, "{{key_ring}}/cryptoKeys/{{name}}") |
| if err != nil { |
| return nil, fmt.Errorf("Error constructing id: %s", err) |
| } |
| d.SetId(id) |
| |
| return []*schema.ResourceData{d}, nil |
| } |
| |
| func flattenKMSCryptoKeyLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| |
| transformed := make(map[string]interface{}) |
| if l, ok := d.GetOkExists("labels"); ok { |
| for k := range l.(map[string]interface{}) { |
| transformed[k] = v.(map[string]interface{})[k] |
| } |
| } |
| |
| return transformed |
| } |
| |
| func flattenKMSCryptoKeyPrimary(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["name"] = |
| flattenKMSCryptoKeyPrimaryName(original["name"], d, config) |
| transformed["state"] = |
| flattenKMSCryptoKeyPrimaryState(original["state"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenKMSCryptoKeyPrimaryName(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyPrimaryState(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyPurpose(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyRotationPeriod(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyVersionTemplate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["algorithm"] = |
| flattenKMSCryptoKeyVersionTemplateAlgorithm(original["algorithm"], d, config) |
| transformed["protection_level"] = |
| flattenKMSCryptoKeyVersionTemplateProtectionLevel(original["protectionLevel"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenKMSCryptoKeyVersionTemplateAlgorithm(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyVersionTemplateProtectionLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyDestroyScheduledDuration(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyImportOnly(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyCryptoKeyBackend(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyKeyAccessJustificationsPolicy(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return nil |
| } |
| original := v.(map[string]interface{}) |
| if len(original) == 0 { |
| return nil |
| } |
| transformed := make(map[string]interface{}) |
| transformed["allowed_access_reasons"] = |
| flattenKMSCryptoKeyKeyAccessJustificationsPolicyAllowedAccessReasons(original["allowedAccessReasons"], d, config) |
| return []interface{}{transformed} |
| } |
| func flattenKMSCryptoKeyKeyAccessJustificationsPolicyAllowedAccessReasons(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func flattenKMSCryptoKeyTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| if v == nil { |
| return v |
| } |
| |
| transformed := make(map[string]interface{}) |
| if l, ok := d.GetOkExists("terraform_labels"); ok { |
| for k := range l.(map[string]interface{}) { |
| transformed[k] = v.(map[string]interface{})[k] |
| } |
| } |
| |
| return transformed |
| } |
| |
| func flattenKMSCryptoKeyEffectiveLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { |
| return v |
| } |
| |
| func expandKMSCryptoKeyPurpose(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyRotationPeriod(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyVersionTemplate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedAlgorithm, err := expandKMSCryptoKeyVersionTemplateAlgorithm(original["algorithm"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedAlgorithm); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["algorithm"] = transformedAlgorithm |
| } |
| |
| transformedProtectionLevel, err := expandKMSCryptoKeyVersionTemplateProtectionLevel(original["protection_level"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedProtectionLevel); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["protectionLevel"] = transformedProtectionLevel |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandKMSCryptoKeyVersionTemplateAlgorithm(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyVersionTemplateProtectionLevel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyDestroyScheduledDuration(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyImportOnly(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyCryptoKeyBackend(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyKeyAccessJustificationsPolicy(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| l := v.([]interface{}) |
| if len(l) == 0 || l[0] == nil { |
| return nil, nil |
| } |
| raw := l[0] |
| original := raw.(map[string]interface{}) |
| transformed := make(map[string]interface{}) |
| |
| transformedAllowedAccessReasons, err := expandKMSCryptoKeyKeyAccessJustificationsPolicyAllowedAccessReasons(original["allowed_access_reasons"], d, config) |
| if err != nil { |
| return nil, err |
| } else if val := reflect.ValueOf(transformedAllowedAccessReasons); val.IsValid() && !tpgresource.IsEmptyValue(val) { |
| transformed["allowedAccessReasons"] = transformedAllowedAccessReasons |
| } |
| |
| return transformed, nil |
| } |
| |
| func expandKMSCryptoKeyKeyAccessJustificationsPolicyAllowedAccessReasons(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { |
| return v, nil |
| } |
| |
| func expandKMSCryptoKeyEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { |
| if v == nil { |
| return map[string]string{}, nil |
| } |
| m := make(map[string]string) |
| for k, val := range v.(map[string]interface{}) { |
| m[k] = val.(string) |
| } |
| return m, nil |
| } |
| |
| func resourceKMSCryptoKeyEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { |
| // if rotationPeriod is set, nextRotationTime must also be set. |
| if d.Get("rotation_period") != "" { |
| rotationPeriod := d.Get("rotation_period").(string) |
| nextRotation, err := kmsCryptoKeyNextRotation(time.Now(), rotationPeriod) |
| |
| if err != nil { |
| return nil, fmt.Errorf("Error setting CryptoKey rotation period: %s", err.Error()) |
| } |
| |
| obj["nextRotationTime"] = nextRotation |
| } |
| |
| // set to false if it is not true explicitly |
| if !(d.Get("skip_initial_version_creation").(bool)) { |
| if err := d.Set("skip_initial_version_creation", false); err != nil { |
| return nil, fmt.Errorf("Error setting skip_initial_version_creation: %s", err) |
| } |
| } |
| |
| return obj, nil |
| } |
| |
| func resourceKMSCryptoKeyUpdateEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { |
| // if rotationPeriod is changed, nextRotationTime must also be set. |
| if d.HasChange("rotation_period") && d.Get("rotation_period") != "" { |
| rotationPeriod := d.Get("rotation_period").(string) |
| nextRotation, err := kmsCryptoKeyNextRotation(time.Now(), rotationPeriod) |
| |
| if err != nil { |
| return nil, fmt.Errorf("Error setting CryptoKey rotation period: %s", err.Error()) |
| } |
| |
| obj["nextRotationTime"] = nextRotation |
| } |
| |
| return obj, nil |
| } |
| |
| func resourceKMSCryptoKeyDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) { |
| // Modify the name to be the user specified form. |
| // We can't just ignore_read on `name` as the linter will |
| // complain that the returned `res` is never used afterwards. |
| // Some field needs to be actually set, and we chose `name`. |
| res["name"] = d.Get("name").(string) |
| return res, nil |
| } |
| |
| func resourceKMSCryptoKeyResourceV0() *schema.Resource { |
| return &schema.Resource{ |
| Schema: map[string]*schema.Schema{ |
| "name": { |
| Type: schema.TypeString, |
| Required: true, |
| }, |
| "key_ring": { |
| Type: schema.TypeString, |
| Required: true, |
| }, |
| "rotation_period": { |
| Type: schema.TypeString, |
| Optional: true, |
| }, |
| "version_template": { |
| Type: schema.TypeList, |
| Optional: true, |
| }, |
| "self_link": { |
| Type: schema.TypeString, |
| }, |
| }, |
| } |
| } |
| |
| func ResourceKMSCryptoKeyUpgradeV0(_ context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { |
| log.Printf("[DEBUG] Attributes before migration: %#v", rawState) |
| |
| config := meta.(*transport_tpg.Config) |
| keyRingId := rawState["key_ring"].(string) |
| parsed, err := parseKmsKeyRingId(keyRingId, config) |
| if err != nil { |
| return nil, err |
| } |
| rawState["key_ring"] = parsed.KeyRingId() |
| |
| log.Printf("[DEBUG] Attributes after migration: %#v", rawState) |
| return rawState, nil |
| } |