From caeeb700e386f7fb0a56d09e85f8f16dc6adc34d Mon Sep 17 00:00:00 2001 From: Harshit Gupta Date: Mon, 22 Mar 2021 18:56:17 +0530 Subject: [PATCH] Key Ring Feature --- go.mod | 2 +- go.sum | 6 +- ibm/data_source_ibm_kms_key.go | 8 +- ibm/data_source_ibm_kms_key_rings.go | 152 +++++++++++ ibm/data_source_ibm_kms_key_rings_test.go | 49 ++++ ibm/data_source_ibm_kms_keys.go | 8 + ibm/provider.go | 3 + ibm/resource_ibm_kms_key.go | 11 + ibm/resource_ibm_kms_key_rings.go | 269 ++++++++++++++++++++ ibm/resource_ibm_kms_key_rings_test.go | 120 +++++++++ website/docs/d/kms_key.html.markdown | 1 + website/docs/d/kms_keys.html.markdown | 1 + website/docs/d/kms_keys_rings.html.markdown | 35 +++ website/docs/r/kms_key.html.markdown | 18 +- website/docs/r/kms_key_rings.html.markdown | 50 ++++ 15 files changed, 719 insertions(+), 14 deletions(-) create mode 100644 ibm/data_source_ibm_kms_key_rings.go create mode 100644 ibm/data_source_ibm_kms_key_rings_test.go create mode 100644 ibm/resource_ibm_kms_key_rings.go create mode 100644 ibm/resource_ibm_kms_key_rings_test.go create mode 100644 website/docs/d/kms_keys_rings.html.markdown create mode 100644 website/docs/r/kms_key_rings.html.markdown diff --git a/go.mod b/go.mod index b16dbe2312..492686cae3 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/IBM/go-sdk-core/v5 v5.2.0 github.com/IBM/ibm-cos-sdk-go v1.3.1 github.com/IBM/ibm-cos-sdk-go-config v1.0.1 - github.com/IBM/keyprotect-go-client v0.6.0 + github.com/IBM/keyprotect-go-client v0.7.0 github.com/IBM/networking-go-sdk v0.12.1 github.com/IBM/platform-services-go-sdk v0.17.17 github.com/IBM/push-notifications-go-sdk v0.0.0-20210310100607-5790b96c47f5 diff --git a/go.sum b/go.sum index f586727695..3650fa118f 100644 --- a/go.sum +++ b/go.sum @@ -84,12 +84,10 @@ github.com/IBM/ibm-cos-sdk-go-config v1.0.1 h1:Nld42UysaZ16hPl4XMnkCgbuwW+s4OVct github.com/IBM/ibm-cos-sdk-go-config v1.0.1/go.mod h1:BAbdv1Zf8mRP6rj40Cem7KgBp+UQn9Fe2EWxIBrp5sM= github.com/IBM/keyprotect-go-client v0.5.2 h1:A4yp2Fc7mg4dtotZErZXwJb9XKpb3ONexnVB+/JqLDM= github.com/IBM/keyprotect-go-client v0.5.2/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= -github.com/IBM/keyprotect-go-client v0.5.3 h1:YGL6vHYQNH3MrtLaSl1ulohE487Jb1KkTpkNKnV4xWU= -github.com/IBM/keyprotect-go-client v0.5.3/go.mod h1:5TwDM/4FRJq1ZOlwQL1xFahLWQ3TveR88VmL1u3njyI= -github.com/IBM/keyprotect-go-client v0.5.4-0.20210127220159-80c013ab9f46 h1:Iyq8BLsDJHkMW1wo1f57JLsfXJOYwDiatCHdUOTWY60= -github.com/IBM/keyprotect-go-client v0.5.4-0.20210127220159-80c013ab9f46/go.mod h1:SVr2ylV/fhSQPDiUjWirN9fsyWFCNNbt8GIT8hPJVjE= github.com/IBM/keyprotect-go-client v0.6.0 h1:jZExoYSaoQ5TrfEzPOmBLc1vJ0VWA0RfKC+Bx39IeGo= github.com/IBM/keyprotect-go-client v0.6.0/go.mod h1:SVr2ylV/fhSQPDiUjWirN9fsyWFCNNbt8GIT8hPJVjE= +github.com/IBM/keyprotect-go-client v0.7.0 h1:JstSHD14Lp6ihwQseyPuGcs1AjOBjAmcisP0dTBA6A0= +github.com/IBM/keyprotect-go-client v0.7.0/go.mod h1:SVr2ylV/fhSQPDiUjWirN9fsyWFCNNbt8GIT8hPJVjE= github.com/IBM/networking-go-sdk v0.12.1 h1:GmzrRjvAyqKMfUPM8Y/R5dce0x5AXTqmseVZ3n7eZks= github.com/IBM/networking-go-sdk v0.12.1/go.mod h1:lzkGBnw5glMB7Nxawfgu19MH4Tjy3KRQ2SYMYl2ck7o= github.com/IBM/platform-services-go-sdk v0.17.17 h1:VXiC6C7h0AsYcsuVVQWKzBhEZ6mM963NbKMUBTkIEvw= diff --git a/ibm/data_source_ibm_kms_key.go b/ibm/data_source_ibm_kms_key.go index 839cd8ccc2..bedd3d7afe 100644 --- a/ibm/data_source_ibm_kms_key.go +++ b/ibm/data_source_ibm_kms_key.go @@ -57,6 +57,11 @@ func dataSourceIBMKMSkey() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "key_ring_id": { + Type: schema.TypeString, + Computed: true, + Description: "The key ring id of the key to be fetched", + }, "crn": { Type: schema.TypeString, Computed: true, @@ -146,7 +151,6 @@ func dataSourceIBMKMSkey() *schema.Resource { }, }, } - } func dataSourceIBMKMSKeyRead(d *schema.ResourceData, meta interface{}) error { @@ -244,6 +248,7 @@ func dataSourceIBMKMSKeyRead(d *schema.ResourceData, meta interface{}) error { keyInstance["crn"] = key.CRN keyInstance["standard_key"] = key.Extractable keyInstance["aliases"] = key.Aliases + keyInstance["key_ring_id"] = key.KeyRingID policies, err := api.GetPolicies(context.Background(), key.ID) if err != nil { return fmt.Errorf("Failed to read policies: %s", err) @@ -273,6 +278,7 @@ func dataSourceIBMKMSKeyRead(d *schema.ResourceData, meta interface{}) error { keyInstance["crn"] = key.CRN keyInstance["standard_key"] = key.Extractable keyInstance["aliases"] = key.Aliases + keyInstance["key_ring_id"] = key.KeyRingID policies, err := api.GetPolicies(context.Background(), key.ID) if err != nil { return fmt.Errorf("Failed to read policies: %s", err) diff --git a/ibm/data_source_ibm_kms_key_rings.go b/ibm/data_source_ibm_kms_key_rings.go new file mode 100644 index 0000000000..4e0ecc79e3 --- /dev/null +++ b/ibm/data_source_ibm_kms_key_rings.go @@ -0,0 +1,152 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "context" + "fmt" + "net/url" + "strings" + + //kp "github.com/IBM/keyprotect-go-client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceIBMKMSkeyRings() *schema.Resource { + return &schema.Resource{ + Read: dataSourceIBMKMSKeyRingsRead, + + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "Key protect or hpcs instance GUID", + }, + "endpoint_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateAllowedStringValue([]string{"public", "private"}), + Description: "public or private", + Default: "public", + }, + "key_rings": { + Type: schema.TypeList, + Computed: true, + Description: "Key Rings for a particualer instance", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeString, + Computed: true, + }, + "creation_date": { + Type: schema.TypeString, + Computed: true, + }, + "created_by": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceIBMKMSKeyRingsRead(d *schema.ResourceData, meta interface{}) error { + api, err := meta.(ClientSession).keyManagementAPI() + if err != nil { + return err + } + + rContollerClient, err := meta.(ClientSession).ResourceControllerAPIV2() + if err != nil { + return err + } + + instanceID := d.Get("instance_id").(string) + endpointType := d.Get("endpoint_type").(string) + + rContollerApi := rContollerClient.ResourceServiceInstanceV2() + + instanceData, err := rContollerApi.GetInstance(instanceID) + if err != nil { + return err + } + instanceCRN := instanceData.Crn.String() + + var hpcsEndpointURL string + crnData := strings.Split(instanceCRN, ":") + + if crnData[4] == "hs-crypto" { + + hpcsEndpointApi, err := meta.(ClientSession).HpcsEndpointAPI() + if err != nil { + return err + } + resp, err := hpcsEndpointApi.Endpoint().GetAPIEndpoint(instanceID) + if err != nil { + return err + } + + if endpointType == "public" { + hpcsEndpointURL = "https://" + resp.Kms.Public + "/api/v2/keys" + } else { + hpcsEndpointURL = "https://" + resp.Kms.Private + "/api/v2/keys" + } + + u, err := url.Parse(hpcsEndpointURL) + if err != nil { + return fmt.Errorf("Error Parsing hpcs EndpointURL") + } + api.URL = u + } else if crnData[4] == "kms" { + if endpointType == "private" { + if !strings.HasPrefix(api.Config.BaseURL, "private") { + api.Config.BaseURL = "private." + api.Config.BaseURL + } + } + } else { + return fmt.Errorf("Invalid or unsupported service Instance") + } + + api.Config.InstanceID = instanceID + keys, err := api.GetKeyRings(context.Background()) + if err != nil { + return fmt.Errorf( + "Get Key Rings failed with error: %s", err) + } + retreivedKeyRings := keys.KeyRings + if keys == nil || len(retreivedKeyRings) == 0 { + return fmt.Errorf("No key Rings in instance %s", instanceID) + } + var keyRingName string + + if len(retreivedKeyRings) == 0 { + return fmt.Errorf("No key Ring with name %s in instance %s", keyRingName, instanceID) + } + + keyRingMap := make([]map[string]interface{}, 0, len(retreivedKeyRings)) + + for _, keyRing := range retreivedKeyRings { + keyInstance := make(map[string]interface{}) + + keyInstance["id"] = keyRing.ID + keyInstance["created_by"] = keyRing.CreatedBy + if keyRing.CreationDate != nil { + keyInstance["creation_date"] = keyRing.CreationDate.String() + } + keyRingMap = append(keyRingMap, keyInstance) + + } + + d.SetId(instanceID) + d.Set("key_rings", keyRingMap) + d.Set("instance_id", instanceID) + d.Set("endpoint_type", endpointType) + + return nil + +} diff --git a/ibm/data_source_ibm_kms_key_rings_test.go b/ibm/data_source_ibm_kms_key_rings_test.go new file mode 100644 index 0000000000..73c6a78bac --- /dev/null +++ b/ibm/data_source_ibm_kms_key_rings_test.go @@ -0,0 +1,49 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMKMSKeyRingDataSource_basic(t *testing.T) { + instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) + // bucketName := fmt.Sprintf("bucket", acctest.RandIntRange(10, 100)) + keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMKmsKeyRingDataSourceConfig(instanceName, keyRing), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("ibm_kms_key_rings.test", "key_ring_id", keyRing), + ), + }, + }, + }) +} + +func testAccCheckIBMKmsKeyRingDataSourceConfig(instanceName, keyRing string) string { + return fmt.Sprintf(` + resource "ibm_resource_instance" "kms_instance" { + name = "%s" + service = "kms" + plan = "tiered-pricing" + location = "us-south" + } + resource "ibm_kms_key_rings" "test" { + instance_id = "${ibm_resource_instance.kms_instance.guid}" + key_ring_id = "%s" + } + data "ibm_kms_key_rings" "test2" { + instance_id = "${ibm_kms_key_rings.test.instance_id}" + } +`, instanceName, keyRing) +} diff --git a/ibm/data_source_ibm_kms_keys.go b/ibm/data_source_ibm_kms_keys.go index ef66b42d20..ef2f658b27 100644 --- a/ibm/data_source_ibm_kms_keys.go +++ b/ibm/data_source_ibm_kms_keys.go @@ -65,6 +65,11 @@ func dataSourceIBMKMSkeys() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "key_ring_id": { + Type: schema.TypeString, + Computed: true, + Description: "The key ring id of the key to be fetched", + }, "standard_key": { Type: schema.TypeBool, Computed: true, @@ -220,6 +225,7 @@ func dataSourceIBMKMSKeysRead(d *schema.ResourceData, meta interface{}) error { keyInstance["crn"] = key.CRN keyInstance["standard_key"] = key.Extractable keyInstance["aliases"] = key.Aliases + keyInstance["key_ring_id"] = key.KeyRingID keyMap = append(keyMap, keyInstance) d.Set("keys", keyMap) @@ -259,6 +265,8 @@ func dataSourceIBMKMSKeysRead(d *schema.ResourceData, meta interface{}) error { keyInstance["name"] = key.Name keyInstance["crn"] = key.CRN keyInstance["standard_key"] = key.Extractable + keyInstance["aliases"] = key.Aliases + keyInstance["key_ring_id"] = key.KeyRingID keyMap = append(keyMap, keyInstance) } diff --git a/ibm/provider.go b/ibm/provider.go index db193df66c..813941296b 100644 --- a/ibm/provider.go +++ b/ibm/provider.go @@ -275,6 +275,7 @@ func Provider() *schema.Provider { "ibm_org": dataSourceIBMOrg(), "ibm_org_quota": dataSourceIBMOrgQuota(), "ibm_kp_key": dataSourceIBMkey(), + "ibm_kms_key_rings": dataSourceIBMKMSkeyRings(), "ibm_kms_keys": dataSourceIBMKMSkeys(), "ibm_pn_application_chrome": dataSourceIBMPNApplicationChrome(), "ibm_kms_key": dataSourceIBMKMSkey(), @@ -479,6 +480,7 @@ func Provider() *schema.Provider { "ibm_pn_application_chrome": resourceIBMPNApplicationChrome(), "ibm_kms_key": resourceIBMKmskey(), "ibm_kms_key_alias": resourceIBMKmskeyAlias(), + "ibm_kms_key_rings": resourceIBMKmskeyRings(), "ibm_kp_key": resourceIBMkey(), "ibm_resource_group": resourceIBMResourceGroup(), "ibm_resource_instance": resourceIBMResourceInstance(), @@ -600,6 +602,7 @@ func Validator() ValidatorDict { "ibm_is_vpc_routing_table_route": resourceIBMISVPCRoutingTableRouteValidator(), "ibm_is_vpn_gateway_connection": resourceIBMISVPNGatewayConnectionValidator(), "ibm_is_vpn_gateway": resourceIBMISVPNGatewayValidator(), + "ibm_kms_key_rings": resourceIBMKeyRingValidator(), "ibm_dns_glb_monitor": resourceIBMPrivateDNSGLBMonitorValidator(), "ibm_dns_glb_pool": resourceIBMPrivateDNSGLBPoolValidator(), }, diff --git a/ibm/resource_ibm_kms_key.go b/ibm/resource_ibm_kms_key.go index 8166069b86..0a5927f8f4 100644 --- a/ibm/resource_ibm_kms_key.go +++ b/ibm/resource_ibm_kms_key.go @@ -36,6 +36,13 @@ func resourceIBMKmskey() *schema.Resource { ForceNew: true, Description: "Key protect or hpcs instance GUID", }, + "key_ring_id": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Default: "default", + Description: "Key Ring for the Key", + }, "key_id": { Type: schema.TypeString, Computed: true, @@ -297,6 +304,9 @@ func resourceIBMKmsKeyCreate(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Invalid or unsupported service Instance") } kpAPI.Config.InstanceID = instanceID + + kpAPI.Config.KeyRing = d.Get("key_ring_id").(string) + name := d.Get("key_name").(string) standardKey := d.Get("standard_key").(bool) @@ -440,6 +450,7 @@ func resourceIBMKmsKeyRead(d *schema.ResourceData, meta interface{}) error { d.Set("endpoint_type", endpointType) d.Set("type", instanceType) d.Set("force_delete", d.Get("force_delete").(bool)) + d.Set("key_ring_id", key.KeyRingID) if key.Expiration != nil { expiration := key.Expiration d.Set("expiration_date", expiration.Format(time.RFC3339)) diff --git a/ibm/resource_ibm_kms_key_rings.go b/ibm/resource_ibm_kms_key_rings.go new file mode 100644 index 0000000000..fa2f21afdd --- /dev/null +++ b/ibm/resource_ibm_kms_key_rings.go @@ -0,0 +1,269 @@ +// Copyright IBM Corp. 2017, 2021 All Rights Reserved. +// Licensed under the Mozilla Public License v2.0 + +package ibm + +import ( + "context" + "fmt" + "net/url" + "strings" + + kp "github.com/IBM/keyprotect-go-client" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceIBMKmskeyRings() *schema.Resource { + return &schema.Resource{ + Create: resourceIBMKmsKeyRingCreate, + Delete: resourceIBMKmsKeyRingDelete, + Read: resourceIBMKmsKeyRingRead, + Importer: &schema.ResourceImporter{}, + + Schema: map[string]*schema.Schema{ + "instance_id": { + Type: schema.TypeString, + Required: true, + Description: "Key protect Instance GUID", + ForceNew: true, + }, + "key_ring_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: "User defined unique ID for the key ring", + ValidateFunc: InvokeValidator("ibm_kms_key_rings", "key_ring_id"), + }, + "endpoint_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validateAllowedStringValue([]string{"public", "private"}), + Description: "public or private", + ForceNew: true, + Default: "public", + }, + }, + } +} + +func resourceIBMKeyRingValidator() *ResourceValidator { + + validateSchema := make([]ValidateSchema, 1) + + validateSchema = append(validateSchema, + ValidateSchema{ + Identifier: "key_ring_id", + ValidateFunctionIdentifier: ValidateRegexpLen, + Type: TypeString, + Required: true, + Regexp: `^[a-zA-Z0-9-]*$`, + MinValueLength: 2, + MaxValueLength: 100}) + + ibmKeyRingResourceValidator := ResourceValidator{ResourceName: "ibm_kms_key_rings", Schema: validateSchema} + return &ibmKeyRingResourceValidator +} + +func resourceIBMKmsKeyRingCreate(d *schema.ResourceData, meta interface{}) error { + kpAPI, err := meta.(ClientSession).keyManagementAPI() + if err != nil { + return err + } + rContollerClient, err := meta.(ClientSession).ResourceControllerAPIV2() + if err != nil { + return err + } + + instanceID := d.Get("instance_id").(string) + endpointType := d.Get("endpoint_type").(string) + keyRingID := d.Get("key_ring_id").(string) + + rContollerAPI := rContollerClient.ResourceServiceInstanceV2() + + instanceData, err := rContollerAPI.GetInstance(instanceID) + if err != nil { + return err + } + instanceCRN := instanceData.Crn.String() + crnData := strings.Split(instanceCRN, ":") + + var hpcsEndpointURL string + + if crnData[4] == "hs-crypto" { + hpcsEndpointAPI, err := meta.(ClientSession).HpcsEndpointAPI() + if err != nil { + return err + } + + resp, err := hpcsEndpointAPI.Endpoint().GetAPIEndpoint(instanceID) + if err != nil { + return err + } + + if endpointType == "public" { + hpcsEndpointURL = "https://" + resp.Kms.Public + "/api/v2/keys" + } else { + hpcsEndpointURL = "https://" + resp.Kms.Private + "/api/v2/keys" + } + + u, err := url.Parse(hpcsEndpointURL) + if err != nil { + return fmt.Errorf("Error Parsing hpcs EndpointURL") + } + kpAPI.URL = u + } else if crnData[4] == "kms" { + if endpointType == "private" { + if !strings.HasPrefix(kpAPI.Config.BaseURL, "private") { + kpAPI.Config.BaseURL = "private." + kpAPI.Config.BaseURL + } + } + } else { + return fmt.Errorf("Invalid or unsupported service Instance") + } + kpAPI.Config.InstanceID = instanceID + + err = kpAPI.CreateKeyRing(context.Background(), keyRingID) + if err != nil { + return fmt.Errorf( + "Error while creating key ring : %s", err) + } + var keyRing string + keyRings, err2 := kpAPI.GetKeyRings(context.Background()) + if err2 != nil { + return fmt.Errorf( + "Error while fetching key ring : %s", err2) + } + for _, v := range keyRings.KeyRings { + if v.ID == keyRingID { + keyRing = v.ID + break + } + } + + d.SetId(fmt.Sprintf("%s:keyRing:%s", keyRing, instanceCRN)) + + return resourceIBMKmsKeyRingRead(d, meta) +} + +func resourceIBMKmsKeyRingRead(d *schema.ResourceData, meta interface{}) error { + kpAPI, err := meta.(ClientSession).keyManagementAPI() + if err != nil { + return err + } + id := strings.Split(d.Id(), ":keyRing:") + crn := id[1] + crnData := strings.Split(crn, ":") + endpointType := crnData[3] + instanceID := crnData[len(crnData)-3] + + var hpcsEndpointURL string + + if crnData[4] == "hs-crypto" { + hpcsEndpointAPI, err := meta.(ClientSession).HpcsEndpointAPI() + if err != nil { + return err + } + + resp, err := hpcsEndpointAPI.Endpoint().GetAPIEndpoint(instanceID) + if err != nil { + return err + } + + if endpointType == "public" { + hpcsEndpointURL = "https://" + resp.Kms.Public + "/api/v2/keys" + } else { + hpcsEndpointURL = "https://" + resp.Kms.Private + "/api/v2/keys" + } + + u, err := url.Parse(hpcsEndpointURL) + if err != nil { + return fmt.Errorf("Error Parsing hpcs EndpointURL") + + } + kpAPI.URL = u + } else if crnData[4] == "kms" { + if endpointType == "private" { + if !strings.HasPrefix(kpAPI.Config.BaseURL, "private") { + kpAPI.Config.BaseURL = "private." + kpAPI.Config.BaseURL + } + } + } else { + return fmt.Errorf("Invalid or unsupported service Instance") + } + + kpAPI.Config.InstanceID = instanceID + _, err = kpAPI.GetKeyRings(context.Background()) + if err != nil { + kpError := err.(*kp.Error) + if kpError.StatusCode == 404 || kpError.StatusCode == 409 { + d.SetId("") + return nil + } + return fmt.Errorf("Get Key Rings failed with error: %s", err) + } + + d.Set("instance_id", instanceID) + d.Set("endpoint_type", endpointType) + d.Set("key_ring_id", id[0]) + return nil +} + +func resourceIBMKmsKeyRingDelete(d *schema.ResourceData, meta interface{}) error { + kpAPI, err := meta.(ClientSession).keyManagementAPI() + if err != nil { + return err + } + id := strings.Split(d.Id(), ":keyRing:") + crn := id[1] + crnData := strings.Split(crn, ":") + endpointType := crnData[3] + instanceID := crnData[len(crnData)-3] + + var hpcsEndpointURL string + + if crnData[4] == "hs-crypto" { + hpcsEndpointAPI, err := meta.(ClientSession).HpcsEndpointAPI() + if err != nil { + return err + } + + resp, err := hpcsEndpointAPI.Endpoint().GetAPIEndpoint(instanceID) + if err != nil { + return err + } + + if endpointType == "public" { + hpcsEndpointURL = "https://" + resp.Kms.Public + "/api/v2/keys" + } else { + hpcsEndpointURL = "https://" + resp.Kms.Private + "/api/v2/keys" + } + + u, err := url.Parse(hpcsEndpointURL) + if err != nil { + return fmt.Errorf("Error Parsing hpcs EndpointURL") + + } + kpAPI.URL = u + } else if crnData[4] == "kms" { + if endpointType == "private" { + if !strings.HasPrefix(kpAPI.Config.BaseURL, "private") { + kpAPI.Config.BaseURL = "private." + kpAPI.Config.BaseURL + } + } + } else { + return fmt.Errorf("Invalid or unsupported service Instance") + } + + kpAPI.Config.InstanceID = instanceID + err1 := kpAPI.DeleteKeyRing(context.Background(), id[0]) + if err1 != nil { + kpError := err1.(*kp.Error) + if kpError.StatusCode == 404 || kpError.StatusCode == 409 { + return nil + } else { + return fmt.Errorf(" failed to Destroy key ring with error: %s", err1) + } + } + return nil + +} diff --git a/ibm/resource_ibm_kms_key_rings_test.go b/ibm/resource_ibm_kms_key_rings_test.go new file mode 100644 index 0000000000..1778c2eaab --- /dev/null +++ b/ibm/resource_ibm_kms_key_rings_test.go @@ -0,0 +1,120 @@ +package ibm + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccIBMKMSResource_Key_Ring_Name(t *testing.T) { + instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) + keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMKmsResourceKeyRingConfig(instanceName, keyRing), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("ibm_kms_key_rings.test", "key_ring_id", keyRing), + ), + }, + }, + }) +} + +func TestAccIBMKMSResource_Key_Ring_Key(t *testing.T) { + instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) + keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) + keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMKmsResourceKeyRingKeyConfig(instanceName, keyRing, keyName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("ibm_kms_key.test", "key_name", keyName), + resource.TestCheckResourceAttr("ibm_kms_key.test", "key_ring_id", keyRing), + ), + }, + }, + }) +} + +func TestAccIBMKMSResource_Key_Ring_Not_Exist(t *testing.T) { + instanceName := fmt.Sprintf("tf_kms_%d", acctest.RandIntRange(10, 100)) + keyName := fmt.Sprintf("key_%d", acctest.RandIntRange(10, 100)) + keyRing := fmt.Sprintf("keyRing%d", acctest.RandIntRange(10, 100)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckIBMKmsResourceKeyRingExistConfig(instanceName, keyName, keyRing), + ExpectError: regexp.MustCompile("KEY_RING_NOT_FOUND_ERR:"), + }, + }, + }) +} + +func testAccCheckIBMKmsResourceKeyRingConfig(instanceName, keyRing string) string { + return fmt.Sprintf(` + resource "ibm_resource_instance" "kms_instance" { + name = "%s" + service = "kms" + plan = "tiered-pricing" + location = "us-south" + } + resource "ibm_kms_key_rings" "test" { + instance_id = ibm_resource_instance.kms_instance.guid + key_ring_id = "%s" + } +`, instanceName, keyRing) +} + +func testAccCheckIBMKmsResourceKeyRingKeyConfig(instanceName, keyRing, keyName string) string { + return fmt.Sprintf(` + resource "ibm_resource_instance" "kms_instance" { + name = "%s" + service = "kms" + plan = "tiered-pricing" + location = "us-south" + } + resource "ibm_kms_key_rings" "key_ring" { + instance_id = ibm_resource_instance.kms_instance.guid + key_ring_id = "%s" + } + resource "ibm_kms_key" "test" { + instance_id = ibm_resource_instance.kms_instance.guid + key_name = "%s" + key_ring_id = ibm_kms_key_rings.key_ring.key_ring_id} + standard_key = true + force_delete = true + } +`, instanceName, keyRing, keyName) +} + +func testAccCheckIBMKmsResourceKeyRingExistConfig(instanceName, keyName, keyRing string) string { + return fmt.Sprintf(` + resource "ibm_resource_instance" "kms_instance" { + name = "%s" + service = "kms" + plan = "tiered-pricing" + location = "us-south" + } + resource "ibm_kms_key" "test" { + instance_id = ibm_resource_instance.kms_instance.guid + key_name = "%s" + key_ring_id = "%s" + standard_key = true + force_delete = true + } +`, instanceName, keyRing, keyName) +} diff --git a/website/docs/d/kms_key.html.markdown b/website/docs/d/kms_key.html.markdown index 7d33bebd22..3297bc8f9d 100644 --- a/website/docs/d/kms_key.html.markdown +++ b/website/docs/d/kms_key.html.markdown @@ -50,6 +50,7 @@ The following attributes are exported: * `name` - The name for the key. * `aliases` - List of all the alias associated with the keys. * `id` - The unique identifier for this key + * `key_ring_id` - The key ring id for the key. * `crn` - The crn of the key. * `standard_key` - This flag is true in case of standard key, else false for root key. * `policy` - The policies associated with the key. diff --git a/website/docs/d/kms_keys.html.markdown b/website/docs/d/kms_keys.html.markdown index d5ba825365..19ea91140f 100644 --- a/website/docs/d/kms_keys.html.markdown +++ b/website/docs/d/kms_keys.html.markdown @@ -41,6 +41,7 @@ The following attributes are exported: * `keys` - List of all Keys in the IBM hs-crypto or Key-protect instance. * `name` - The name for the key. * `aliases` - List of all the alias associated with the keys. + * `key_ring_id` - The key ring id for the key. * `id` - The unique identifier for this key * `crn` - The crn of the key. * `standard_key` - This flag is true in case of standard key, else false for root key. diff --git a/website/docs/d/kms_keys_rings.html.markdown b/website/docs/d/kms_keys_rings.html.markdown new file mode 100644 index 0000000000..7de8e9ad4a --- /dev/null +++ b/website/docs/d/kms_keys_rings.html.markdown @@ -0,0 +1,35 @@ +--- +subcategory: "Key Management Service" +layout: "ibm" +page_title: "IBM : kms-key-rings" +description: |- + Manages key rings for IBM hs-crypto or key-protect. +--- + +# ibm\_kms_key_rings + +Retreives a list of key rings from the hs-crypto or key-protect instance. Import the details of existing keyrings of hs-crypto and kms instance as a read-only data source. You can then reference the fields of the data source in other resources within the same configuration using interpolation syntax. + +## Example Usage + +```hcl +data "ibm_kms_key_rings" "test" { + instance_id = "guid-of-keyprotect-or hs-crypto-instance" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance_id` - (Required, string) The keyprotect instance guid. +* `endpoint_type` - (Optional, string) The type of the endpoint (public or private) to be used for fetching keys. + +## Attribute Reference + +The following attributes are exported: + +* `key_rings` - List of all Key Rings in the IBM hs-crypto or Key-protect instance. + * `id` - The unique identifier for the key ring + * `creation_date` - The date the key ring was created. The date format follows RFC 3339. + * `created_by` - The unique identifier for the resource that created the key ring. \ No newline at end of file diff --git a/website/docs/r/kms_key.html.markdown b/website/docs/r/kms_key.html.markdown index f87f82da34..a4d18a1368 100644 --- a/website/docs/r/kms_key.html.markdown +++ b/website/docs/r/kms_key.html.markdown @@ -118,10 +118,11 @@ resource "ibm_kms_key" "key" { The following arguments are supported: * `instance_id` - (Required, Forces new resource, string) The hs-crypto or key-protect instance guid. -* `key_name` - (Required, Forces new resource, string) The name of the key. -* `standard_key` - (Optional, Forces new resource, bool) set to true to create a standard key, to create a root key set this flag to false. Default is false -* `endpoint_type` - (Optional, Forces new resource, string) The type of the endpoint (public or private) to be used for creating keys. -* `payload` - (Optional, Forces new resource, string) The base64 encoded key material that you want to store and manage in the service. To import an existing key, provide a 256-bit key. To generate a new key, omit this parameter. +* `key_name` - (Required, Forces new resource, string) The name of the key. +* `key_ring_id` - (Optional, Forces new resource, string) The Key Ring ID name for the key. Default: default +* `standard_key` - (Optional, Forces new resource, bool) set to true to create a standard key, to create a root key set this flag to false. Default is false +* `endpoint_type` - (Optional, Forces new resource, string) The type of the endpoint (public or private) to be used for creating keys. +* `payload` - (Optional, Forces new resource, string) The base64 encoded key material that you want to store and manage in the service. To import an existing key, provide a 256-bit key. To generate a new key, omit this parameter. * `encrypted_nonce` - (Optional, Forces new resource, string) The encrypted nonce value that verifies your request to import a key to Key Protect. This value must be encrypted by using the key material that you want to import to the service. To retrieve a nonce, use `ibmcloud kp import-token get`. Then, encrypt the value by running `ibmcloud kp import-token encrypt-nonce`. Only for imported root key. * `iv_value` - (Optional, Forces new resource, string) Used with import tokens. The initialization vector (IV) that is generated when you encrypt a nonce. The IV value is required to decrypt the encrypted nonce value that you provide when you make a key import request to the service. To generate an IV, encrypt the nonce by running `ibmcloud kp import-token encrypt-nonce`. Only for imported root key. * `force_delete` - (Optional, bool) If set to true, Key Protect forces deletion on a key that is protecting a cloud resource, such as a Cloud Object Storage bucket. The action removes any registrations that are associated with the key. Note: If a key is protecting a cloud resource that has a retention policy, Key Protect cannot delete the key. Default: false. @@ -142,11 +143,12 @@ The following arguments are supported: The following attributes are exported: -* `id` - The crn of the key. -* `crn` - The crn of the key. +* `id` - The crn of the key. +* `crn` - The crn of the key. +* `key_ring_id` - The key ring id of the key. * `status` - The status of the key. -* `key_id` - The id of the key. -* `type` - The type of the key kms or hs-crypto. +* `key_id` - The id of the key. +* `type` - The type of the key kms or hs-crypto. * `policy` - The policies associated with the key. * `rotation` - The key rotation time interval in months, with a minimum of 1, and a maximum of 12. * `created_by` - The unique identifier for the resource that created the policy. diff --git a/website/docs/r/kms_key_rings.html.markdown b/website/docs/r/kms_key_rings.html.markdown new file mode 100644 index 0000000000..46618c248a --- /dev/null +++ b/website/docs/r/kms_key_rings.html.markdown @@ -0,0 +1,50 @@ +--- +subcategory: "Key Management Service" +layout: "ibm" +page_title: "IBM : kms-key-rings" +description: |- + Manages key rings for IBM hs-crypto and kms. +--- + +# ibm\_kms_key_rings + +Provides a resource to manage key rings for hs-crypto and key-protect services. This allows key rings to be created, and deleted. Key rings created through this resource can be used to associate to kms key resource when a standard or a root key gets created or imported. + + +## Example usage to create a Key Ring and associate a kms key. + +```hcl +resource "ibm_resource_instance" "kms_instance" { + name = "instance-name" + service = "kms" + plan = "tiered-pricing" + location = "us-south" +} +resource "ibm_kms_key_rings" "keyRing" { + instance_id = ibm_resource_instance.kms_instance.guid + key_ring_id = "key-ring-id" +} +resource "ibm_kms_key" "key" { + instance_id = ibm_resource_instance.kp_instance.guid + key_name = "key" + key_ring_id = ibm_kms_key_rings.keyRing.key_ring_id + standard_key = false + payload = "aW1wb3J0ZWQucGF5bG9hZA==" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `instance_id` - (Required, Forces new resource, string) The hs-crypto or key-protect instance guid. +* `key_ring_id` - (Required, Forces new resource, string) The ID that identifies the key ring. Each ID is unique only within the given instance and is not reserved across the Key Protect service. +Constraints: 2 ≤ length ≤ 100, Value must match regular expression ^[a-zA-Z0-9-]*$ +* `endpoint_type` - (Optional, Forces new resource, string) The type of the endpoint (public or private) to be used for creating keys. + +## Attribute Reference + +The following attributes are exported: + +* `id` - Unique Identifier for the terraform resource. +* `key_ring_id` - The key ring ID.