From d8c42e1e14ce677016cbcb8a954aae5a7f1a8462 Mon Sep 17 00:00:00 2001 From: SevenEarth <45937856+SevenEarth@users.noreply.github.com> Date: Sun, 8 Oct 2023 07:20:02 -0500 Subject: [PATCH] feat/ssm (#2172) * feat/ssm * feat/ssm --- .changelog/2172.txt | 19 +++ .../data_source_tc_ssm_rotation_detail.go | 118 +++++++++++++ ...data_source_tc_ssm_rotation_detail_test.go | 32 ++++ .../data_source_tc_ssm_rotation_history.go | 91 ++++++++++ ...ata_source_tc_ssm_rotation_history_test.go | 32 ++++ .../data_source_tc_ssm_service_status.go | 96 +++++++++++ .../data_source_tc_ssm_service_status_test.go | 29 ++++ .../data_source_tc_ssm_ssh_key_pair_value.go | 161 ++++++++++++++++++ ...a_source_tc_ssm_ssh_key_pair_value_test.go | 35 ++++ tencentcloud/provider.go | 10 ++ .../resource_tc_ssm_rotate_product_secret.go | 115 +++++++++++++ ...ource_tc_ssm_rotate_product_secret_test.go | 33 ++++ tencentcloud/service_tencentcloud_ssm.go | 142 +++++++++++++++ .../docs/d/ssm_rotation_detail.html.markdown | 38 +++++ .../docs/d/ssm_rotation_history.html.markdown | 35 ++++ .../docs/d/ssm_service_status.html.markdown | 34 ++++ .../d/ssm_ssh_key_pair_value.html.markdown | 59 +++++++ .../r/ssm_rotate_product_secret.html.markdown | 35 ++++ website/tencentcloud.erb | 15 ++ 19 files changed, 1129 insertions(+) create mode 100644 .changelog/2172.txt create mode 100644 tencentcloud/data_source_tc_ssm_rotation_detail.go create mode 100644 tencentcloud/data_source_tc_ssm_rotation_detail_test.go create mode 100644 tencentcloud/data_source_tc_ssm_rotation_history.go create mode 100644 tencentcloud/data_source_tc_ssm_rotation_history_test.go create mode 100644 tencentcloud/data_source_tc_ssm_service_status.go create mode 100644 tencentcloud/data_source_tc_ssm_service_status_test.go create mode 100644 tencentcloud/data_source_tc_ssm_ssh_key_pair_value.go create mode 100644 tencentcloud/data_source_tc_ssm_ssh_key_pair_value_test.go create mode 100644 tencentcloud/resource_tc_ssm_rotate_product_secret.go create mode 100644 tencentcloud/resource_tc_ssm_rotate_product_secret_test.go create mode 100644 website/docs/d/ssm_rotation_detail.html.markdown create mode 100644 website/docs/d/ssm_rotation_history.html.markdown create mode 100644 website/docs/d/ssm_service_status.html.markdown create mode 100644 website/docs/d/ssm_ssh_key_pair_value.html.markdown create mode 100644 website/docs/r/ssm_rotate_product_secret.html.markdown diff --git a/.changelog/2172.txt b/.changelog/2172.txt new file mode 100644 index 0000000000..b8441b4908 --- /dev/null +++ b/.changelog/2172.txt @@ -0,0 +1,19 @@ +```release-note:new-resource +tencentcloud_ssm_rotate_product_secret +``` + +```release-note:new-data-source +tencentcloud_ssm_rotation_detail +``` + +```release-note:new-data-source +tencentcloud_ssm_rotation_history +``` + +```release-note:new-data-source +tencentcloud_ssm_service_status +``` + +```release-note:new-data-source +tencentcloud_ssm_ssh_key_pair_value +``` diff --git a/tencentcloud/data_source_tc_ssm_rotation_detail.go b/tencentcloud/data_source_tc_ssm_rotation_detail.go new file mode 100644 index 0000000000..05fb36d12e --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_rotation_detail.go @@ -0,0 +1,118 @@ +/* +Use this data source to query detailed information of ssm rotation_detail + +Example Usage + +```hcl +data "tencentcloud_ssm_rotation_detail" "example" { + secret_name = "tf_example" +} +``` +*/ +package tencentcloud + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + ssm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm/v20190923" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudSsmRotationDetail() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudSsmRotationDetailRead, + Schema: map[string]*schema.Schema{ + "secret_name": { + Required: true, + Type: schema.TypeString, + Description: "Secret name.", + }, + "enable_rotation": { + Computed: true, + Type: schema.TypeBool, + Description: "Whether to allow rotation.", + }, + "frequency": { + Computed: true, + Type: schema.TypeInt, + Description: "The rotation frequency, in days, defaults to 1 day.", + }, + "latest_rotate_time": { + Computed: true, + Type: schema.TypeString, + Description: "Time of last rotation.", + }, + "next_rotate_begin_time": { + Computed: true, + Type: schema.TypeString, + Description: "The time to start the next rotation.", + }, + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + }, + } +} + +func dataSourceTencentCloudSsmRotationDetailRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("data_source.tencentcloud_ssm_rotation_detail.read")() + defer inconsistentCheck(d, meta)() + + var ( + logId = getLogId(contextNil) + ctx = context.WithValue(context.TODO(), logIdKey, logId) + service = SsmService{client: meta.(*TencentCloudClient).apiV3Conn} + rotationDetail *ssm.DescribeRotationDetailResponseParams + secretName string + ) + + paramMap := make(map[string]interface{}) + if v, ok := d.GetOk("secret_name"); ok { + paramMap["SecretName"] = helper.String(v.(string)) + secretName = v.(string) + } + + err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeSsmRotationDetailByFilter(ctx, paramMap) + if e != nil { + return retryError(e) + } + + rotationDetail = result + return nil + }) + + if err != nil { + return err + } + + if rotationDetail.EnableRotation != nil { + _ = d.Set("enable_rotation", rotationDetail.EnableRotation) + } + + if rotationDetail.Frequency != nil { + _ = d.Set("frequency", rotationDetail.Frequency) + } + + if rotationDetail.LatestRotateTime != nil { + _ = d.Set("latest_rotate_time", rotationDetail.LatestRotateTime) + } + + if rotationDetail.NextRotateBeginTime != nil { + _ = d.Set("next_rotate_begin_time", rotationDetail.NextRotateBeginTime) + } + + d.SetId(secretName) + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if e := writeToFile(output.(string), d); e != nil { + return e + } + } + + return nil +} diff --git a/tencentcloud/data_source_tc_ssm_rotation_detail_test.go b/tencentcloud/data_source_tc_ssm_rotation_detail_test.go new file mode 100644 index 0000000000..4cdefb1a8a --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_rotation_detail_test.go @@ -0,0 +1,32 @@ +package tencentcloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +// go test -i; go test -test.run TestAccTencentCloudNeedFixSsmRotationDetailDataSource_basic -v +func TestAccTencentCloudNeedFixSsmRotationDetailDataSource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccSsmRotationDetailDataSource, + Check: resource.ComposeTestCheckFunc( + testAccCheckTencentCloudDataSourceID("data.tencentcloud_ssm_rotation_detail.example"), + ), + }, + }, + }) +} + +const testAccSsmRotationDetailDataSource = ` +data "tencentcloud_ssm_rotation_detail" "example" { + secret_name = "tf_example" +} +` diff --git a/tencentcloud/data_source_tc_ssm_rotation_history.go b/tencentcloud/data_source_tc_ssm_rotation_history.go new file mode 100644 index 0000000000..9cfb21ee07 --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_rotation_history.go @@ -0,0 +1,91 @@ +/* +Use this data source to query detailed information of ssm rotation_history + +Example Usage + +```hcl +data "tencentcloud_ssm_rotation_history" "example" { + secret_name = "keep_terraform" +} +``` +*/ +package tencentcloud + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudSsmRotationHistory() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudSsmRotationHistoryRead, + Schema: map[string]*schema.Schema{ + "secret_name": { + Required: true, + Type: schema.TypeString, + Description: "Secret name.", + }, + "version_ids": { + Computed: true, + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Description: "The number of version numbers. The maximum number of version numbers that can be displayed to users is 10.", + }, + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + }, + } +} + +func dataSourceTencentCloudSsmRotationHistoryRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("data_source.tencentcloud_ssm_rotation_history.read")() + defer inconsistentCheck(d, meta)() + + var ( + logId = getLogId(contextNil) + ctx = context.WithValue(context.TODO(), logIdKey, logId) + service = SsmService{client: meta.(*TencentCloudClient).apiV3Conn} + versionIDs []*string + secretName string + ) + + paramMap := make(map[string]interface{}) + if v, ok := d.GetOk("secret_name"); ok { + paramMap["SecretName"] = helper.String(v.(string)) + secretName = v.(string) + } + + err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeSsmRotationHistoryByFilter(ctx, paramMap) + if e != nil { + return retryError(e) + } + + versionIDs = result + return nil + }) + + if err != nil { + return err + } + + if versionIDs != nil { + _ = d.Set("version_ids", versionIDs) + } + + d.SetId(secretName) + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if e := writeToFile(output.(string), d); e != nil { + return e + } + } + + return nil +} diff --git a/tencentcloud/data_source_tc_ssm_rotation_history_test.go b/tencentcloud/data_source_tc_ssm_rotation_history_test.go new file mode 100644 index 0000000000..7866b1b594 --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_rotation_history_test.go @@ -0,0 +1,32 @@ +package tencentcloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +// go test -i; go test -test.run TestAccTencentCloudNeedFixSsmRotationHistoryDataSource_basic -v +func TestAccTencentCloudNeedFixSsmRotationHistoryDataSource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccSsmRotationHistoryDataSource, + Check: resource.ComposeTestCheckFunc( + testAccCheckTencentCloudDataSourceID("data.tencentcloud_ssm_rotation_history.example"), + ), + }, + }, + }) +} + +const testAccSsmRotationHistoryDataSource = ` +data "tencentcloud_ssm_rotation_history" "example" { + secret_name = "keep_terraform" +} +` diff --git a/tencentcloud/data_source_tc_ssm_service_status.go b/tencentcloud/data_source_tc_ssm_service_status.go new file mode 100644 index 0000000000..76c5474043 --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_service_status.go @@ -0,0 +1,96 @@ +/* +Use this data source to query detailed information of ssm service_status + +Example Usage + +```hcl +data "tencentcloud_ssm_service_status" "example" {} +``` +*/ +package tencentcloud + +import ( + "context" + "strconv" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + ssm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm/v20190923" +) + +func dataSourceTencentCloudSsmServiceStatus() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudSsmServiceStatusRead, + Schema: map[string]*schema.Schema{ + "service_enabled": { + Computed: true, + Type: schema.TypeBool, + Description: "True means the service has been activated, false means the service has not been activated yet.", + }, + "invalid_type": { + Computed: true, + Type: schema.TypeInt, + Description: "Service unavailability type: 0-Not purchased, 1-Normal, 2-Service suspended due to arrears, 3-Resource release.", + }, + "access_key_escrow_enabled": { + Computed: true, + Type: schema.TypeBool, + Description: "True means that the user can already use the key safe hosting function, false means that the user cannot use the key safe hosting function temporarily.", + }, + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + }, + } +} + +func dataSourceTencentCloudSsmServiceStatusRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("data_source.tencentcloud_ssm_service_status.read")() + defer inconsistentCheck(d, meta)() + + var ( + logId = getLogId(contextNil) + ctx = context.WithValue(context.TODO(), logIdKey, logId) + service = SsmService{client: meta.(*TencentCloudClient).apiV3Conn} + serviceStatus *ssm.GetServiceStatusResponseParams + ) + + err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeSsmServiceStatusByFilter(ctx) + if e != nil { + return retryError(e) + } + + serviceStatus = result + return nil + }) + + if err != nil { + return err + } + + if serviceStatus.ServiceEnabled != nil { + _ = d.Set("service_enabled", serviceStatus.ServiceEnabled) + } + + if serviceStatus.InvalidType != nil { + _ = d.Set("invalid_type", serviceStatus.InvalidType) + } + + if serviceStatus.AccessKeyEscrowEnabled != nil { + _ = d.Set("access_key_escrow_enabled", serviceStatus.AccessKeyEscrowEnabled) + } + + d.SetId(strconv.FormatInt(time.Now().Unix(), 10)) + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if e := writeToFile(output.(string), d); e != nil { + return e + } + } + + return nil +} diff --git a/tencentcloud/data_source_tc_ssm_service_status_test.go b/tencentcloud/data_source_tc_ssm_service_status_test.go new file mode 100644 index 0000000000..8c0bd77dc7 --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_service_status_test.go @@ -0,0 +1,29 @@ +package tencentcloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +// go test -i; go test -test.run TestAccTencentCloudSsmServiceStatusDataSource_basic -v +func TestAccTencentCloudSsmServiceStatusDataSource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccSsmServiceStatusDataSource, + Check: resource.ComposeTestCheckFunc( + testAccCheckTencentCloudDataSourceID("data.tencentcloud_ssm_service_status.example")), + }, + }, + }) +} + +const testAccSsmServiceStatusDataSource = ` +data "tencentcloud_ssm_service_status" "example" {} +` diff --git a/tencentcloud/data_source_tc_ssm_ssh_key_pair_value.go b/tencentcloud/data_source_tc_ssm_ssh_key_pair_value.go new file mode 100644 index 0000000000..5fca70e6b9 --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_ssh_key_pair_value.go @@ -0,0 +1,161 @@ +/* +Use this data source to query detailed information of ssm ssh_key_pair_value + +~> **NOTE:** Must set at least one of `secret_name` or `ssh_key_id`. + +Example Usage + +```hcl +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + secret_name = "keep_terraform" + ssh_key_id = "skey-2ae2snwd" +} +``` + +Or + +```hcl +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + secret_name = "keep_terraform" +} +``` + +Or + +```hcl +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + ssh_key_id = "skey-2ae2snwd" +} +``` +*/ +package tencentcloud + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + ssm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm/v20190923" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func dataSourceTencentCloudSsmSshKeyPairValue() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudSsmSshKeyPairValueRead, + Schema: map[string]*schema.Schema{ + "secret_name": { + Optional: true, + Computed: true, + Type: schema.TypeString, + Description: "Secret name.", + }, + "ssh_key_id": { + Optional: true, + Computed: true, + Type: schema.TypeString, + Description: "The key pair ID is the unique identifier of the key pair in the cloud server.", + }, + "public_key": { + Computed: true, + Type: schema.TypeString, + Description: "Public key plain text, encoded using base64.", + }, + "private_key": { + Computed: true, + Type: schema.TypeString, + Description: "Private key plain text, encoded using base64.", + }, + "project_id": { + Computed: true, + Type: schema.TypeInt, + Description: "The project ID to which this key pair belongs.", + }, + "ssh_key_name": { + Computed: true, + Type: schema.TypeString, + Description: "SSH key name.", + }, + "ssh_key_description": { + Computed: true, + Type: schema.TypeString, + Description: "Description of the SSH key pair. Users can modify the description information of the key pair in the CVM console.", + }, + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + }, + } +} + +func dataSourceTencentCloudSsmSshKeyPairValueRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("data_source.tencentcloud_ssm_ssh_key_pair_value.read")() + defer inconsistentCheck(d, meta)() + + var ( + logId = getLogId(contextNil) + ctx = context.WithValue(context.TODO(), logIdKey, logId) + service = SsmService{client: meta.(*TencentCloudClient).apiV3Conn} + sshKeyPairValue *ssm.GetSSHKeyPairValueResponseParams + sshKeyID string + ) + + paramMap := make(map[string]interface{}) + if v, ok := d.GetOk("secret_name"); ok { + paramMap["SecretName"] = helper.String(v.(string)) + } + + if v, ok := d.GetOk("ssh_key_id"); ok { + paramMap["SSHKeyId"] = helper.String(v.(string)) + } + + err := resource.Retry(readRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeSsmSshKeyPairValueByFilter(ctx, paramMap) + if e != nil { + return retryError(e) + } + + sshKeyPairValue = result + return nil + }) + + if err != nil { + return err + } + + if sshKeyPairValue.SSHKeyID != nil { + _ = d.Set("ssh_key_id", sshKeyPairValue.SSHKeyID) + sshKeyID = *sshKeyPairValue.SSHKeyID + } + + if sshKeyPairValue.SSHKeyName != nil { + _ = d.Set("ssh_key_name", sshKeyPairValue.SSHKeyName) + } + + if sshKeyPairValue.PublicKey != nil { + _ = d.Set("public_key", sshKeyPairValue.PublicKey) + } + + if sshKeyPairValue.PrivateKey != nil { + _ = d.Set("private_key", sshKeyPairValue.PrivateKey) + } + + if sshKeyPairValue.ProjectID != nil { + _ = d.Set("project_id", sshKeyPairValue.ProjectID) + } + + if sshKeyPairValue.SSHKeyDescription != nil { + _ = d.Set("ssh_key_description", sshKeyPairValue.SSHKeyDescription) + } + + d.SetId(sshKeyID) + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if e := writeToFile(output.(string), d); e != nil { + return e + } + } + + return nil +} diff --git a/tencentcloud/data_source_tc_ssm_ssh_key_pair_value_test.go b/tencentcloud/data_source_tc_ssm_ssh_key_pair_value_test.go new file mode 100644 index 0000000000..5e208a02d2 --- /dev/null +++ b/tencentcloud/data_source_tc_ssm_ssh_key_pair_value_test.go @@ -0,0 +1,35 @@ +package tencentcloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +// go test -i; go test -test.run TestAccTencentCloudSsmSshKeyPairValueDataSource_basic -v +func TestAccTencentCloudSsmSshKeyPairValueDataSource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccSsmSshKeyPairValueDataSource, + Check: resource.ComposeTestCheckFunc( + testAccCheckTencentCloudDataSourceID("data.tencentcloud_ssm_ssh_key_pair_value.example"), + resource.TestCheckResourceAttrSet("data.tencentcloud_ssm_ssh_key_pair_value.example", "secret_name"), + resource.TestCheckResourceAttrSet("data.tencentcloud_ssm_ssh_key_pair_value.example", "ssh_key_id"), + ), + }, + }, + }) +} + +const testAccSsmSshKeyPairValueDataSource = ` +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + secret_name = "keep_terraform" + ssh_key_id = "skey-2ae2snwd" +} +` diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 251ff51199..2aac1eb6f2 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -890,12 +890,17 @@ Secrets Manager(SSM) tencentcloud_ssm_products tencentcloud_ssm_secrets tencentcloud_ssm_secret_versions + tencentcloud_ssm_rotation_detail + tencentcloud_ssm_rotation_history + tencentcloud_ssm_service_status + tencentcloud_ssm_ssh_key_pair_value Resource tencentcloud_ssm_secret tencentcloud_ssm_secret_version tencentcloud_ssm_product_secret tencentcloud_ssm_ssh_key_pair_secret + tencentcloud_ssm_rotate_product_secret TcaplusDB Data Source @@ -2154,6 +2159,10 @@ func Provider() *schema.Provider { "tencentcloud_ssm_products": dataSourceTencentCloudSsmProducts(), "tencentcloud_ssm_secrets": dataSourceTencentCloudSsmSecrets(), "tencentcloud_ssm_secret_versions": dataSourceTencentCloudSsmSecretVersions(), + "tencentcloud_ssm_rotation_detail": dataSourceTencentCloudSsmRotationDetail(), + "tencentcloud_ssm_rotation_history": dataSourceTencentCloudSsmRotationHistory(), + "tencentcloud_ssm_service_status": dataSourceTencentCloudSsmServiceStatus(), + "tencentcloud_ssm_ssh_key_pair_value": dataSourceTencentCloudSsmSshKeyPairValue(), "tencentcloud_cdh_instances": dataSourceTencentCloudCdhInstances(), "tencentcloud_dayu_eip": dataSourceTencentCloudDayuEip(), "tencentcloud_teo_zone_available_plans": dataSourceTencentCloudTeoZoneAvailablePlans(), @@ -2841,6 +2850,7 @@ func Provider() *schema.Provider { "tencentcloud_ssm_ssh_key_pair_secret": resourceTencentCloudSsmSshKeyPairSecret(), "tencentcloud_ssm_product_secret": resourceTencentCloudSsmProductSecret(), "tencentcloud_ssm_secret_version": resourceTencentCloudSsmSecretVersion(), + "tencentcloud_ssm_rotate_product_secret": resourceTencentCloudSsmRotateProductSecret(), "tencentcloud_cdh_instance": resourceTencentCloudCdhInstance(), "tencentcloud_dnspod_domain_instance": resourceTencentCloudDnspodDomainInstance(), "tencentcloud_dnspod_record": resourceTencentCloudDnspodRecord(), diff --git a/tencentcloud/resource_tc_ssm_rotate_product_secret.go b/tencentcloud/resource_tc_ssm_rotate_product_secret.go new file mode 100644 index 0000000000..6c5335c0c2 --- /dev/null +++ b/tencentcloud/resource_tc_ssm_rotate_product_secret.go @@ -0,0 +1,115 @@ +/* +Provides a resource to create a ssm rotate_product_secret + +Example Usage + +```hcl +resource "tencentcloud_ssm_rotate_product_secret" "example" { + secret_name = "tf_example" +} +``` +*/ +package tencentcloud + +import ( + "fmt" + "log" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + ssm "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ssm/v20190923" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func resourceTencentCloudSsmRotateProductSecret() *schema.Resource { + return &schema.Resource{ + Create: resourceTencentCloudSsmRotateProductSecretCreate, + Read: resourceTencentCloudSsmRotateProductSecretRead, + Delete: resourceTencentCloudSsmRotateProductSecretDelete, + + Schema: map[string]*schema.Schema{ + "secret_name": { + Required: true, + ForceNew: true, + Type: schema.TypeString, + Description: "Secret name.", + }, + }, + } +} + +func resourceTencentCloudSsmRotateProductSecretCreate(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_ssm_rotate_product_secret.create")() + defer inconsistentCheck(d, meta)() + + var ( + logId = getLogId(contextNil) + request = ssm.NewRotateProductSecretRequest() + response = ssm.NewRotateProductSecretResponse() + asyncRequest = ssm.NewDescribeAsyncRequestInfoRequest() + secretName string + flowId int64 + ) + + if v, ok := d.GetOk("secret_name"); ok { + request.SecretName = helper.String(v.(string)) + secretName = v.(string) + } + + err := resource.Retry(writeRetryTimeout, func() *resource.RetryError { + result, e := meta.(*TencentCloudClient).apiV3Conn.UseSsmClient().RotateProductSecret(request) + if e != nil { + return retryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + + response = result + return nil + }) + + if err != nil { + log.Printf("[CRITAL]%s operate ssm rotateProductSecret failed, reason:%+v", logId, err) + return err + } + + // wait + flowId = *response.Response.FlowID + asyncRequest.FlowID = &flowId + err = resource.Retry(writeRetryTimeout*3, func() *resource.RetryError { + result, e := meta.(*TencentCloudClient).apiV3Conn.UseSsmClient().DescribeAsyncRequestInfo(asyncRequest) + if e != nil { + return retryError(e) + } else { + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), result.ToJsonString()) + } + + if *result.Response.TaskStatus == 1 { + return nil + } + + return resource.RetryableError(fmt.Errorf("operate ssm describeAsyncRequestInfo status is %d", *result.Response.TaskStatus)) + }) + + if err != nil { + log.Printf("[CRITAL]%s operate ssm describeAsyncRequestInfo failed, reason:%+v", logId, err) + return err + } + + d.SetId(secretName) + return resourceTencentCloudSsmRotateProductSecretRead(d, meta) +} + +func resourceTencentCloudSsmRotateProductSecretRead(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_ssm_rotate_product_secret.read")() + defer inconsistentCheck(d, meta)() + + return nil +} + +func resourceTencentCloudSsmRotateProductSecretDelete(d *schema.ResourceData, meta interface{}) error { + defer logElapsed("resource.tencentcloud_ssm_rotate_product_secret.delete")() + defer inconsistentCheck(d, meta)() + + return nil +} diff --git a/tencentcloud/resource_tc_ssm_rotate_product_secret_test.go b/tencentcloud/resource_tc_ssm_rotate_product_secret_test.go new file mode 100644 index 0000000000..ef495c6bbe --- /dev/null +++ b/tencentcloud/resource_tc_ssm_rotate_product_secret_test.go @@ -0,0 +1,33 @@ +package tencentcloud + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +// go test -i; go test -test.run TestAccTencentCloudNeedFixSsmRotateProductSecretResource_basic -v +func TestAccTencentCloudNeedFixSsmRotateProductSecretResource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccSsmRotateProductSecret, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("tencentcloud_ssm_rotate_product_secret.example", "id"), + resource.TestCheckResourceAttrSet("tencentcloud_ssm_rotate_product_secret.example", "secret_name"), + ), + }, + }, + }) +} + +const testAccSsmRotateProductSecret = ` +resource "tencentcloud_ssm_rotate_product_secret" "example" { + secret_name = "tf_example" +} +` diff --git a/tencentcloud/service_tencentcloud_ssm.go b/tencentcloud/service_tencentcloud_ssm.go index 177b1eb2e4..cf09324249 100644 --- a/tencentcloud/service_tencentcloud_ssm.go +++ b/tencentcloud/service_tencentcloud_ssm.go @@ -514,3 +514,145 @@ func (me *SsmService) DescribeSsmProductsByFilter(ctx context.Context) (products return } + +func (me *SsmService) DescribeSsmRotationDetailByFilter(ctx context.Context, param map[string]interface{}) (rotationDetail *ssm.DescribeRotationDetailResponseParams, errRet error) { + var ( + logId = getLogId(ctx) + request = ssm.NewDescribeRotationDetailRequest() + ) + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + for k, v := range param { + if k == "SecretName" { + request.SecretName = v.(*string) + } + } + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseSsmClient().DescribeRotationDetail(request) + if err != nil { + errRet = err + return + } + + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if response == nil { + return + } + + rotationDetail = response.Response + return +} + +func (me *SsmService) DescribeSsmRotationHistoryByFilter(ctx context.Context, param map[string]interface{}) (rotationHistory []*string, errRet error) { + var ( + logId = getLogId(ctx) + request = ssm.NewDescribeRotationHistoryRequest() + ) + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + for k, v := range param { + if k == "SecretName" { + request.SecretName = v.(*string) + } + } + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseSsmClient().DescribeRotationHistory(request) + if err != nil { + errRet = err + return + } + + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if response == nil || len(response.Response.VersionIDs) < 1 { + return + } + + rotationHistory = response.Response.VersionIDs + return +} + +func (me *SsmService) DescribeSsmServiceStatusByFilter(ctx context.Context) (ServiceStatus *ssm.GetServiceStatusResponseParams, errRet error) { + var ( + logId = getLogId(ctx) + request = ssm.NewGetServiceStatusRequest() + ) + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseSsmClient().GetServiceStatus(request) + if err != nil { + errRet = err + return + } + + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if response == nil { + return + } + + ServiceStatus = response.Response + return +} + +func (me *SsmService) DescribeSsmSshKeyPairValueByFilter(ctx context.Context, param map[string]interface{}) (sshKeyPairValue *ssm.GetSSHKeyPairValueResponseParams, errRet error) { + var ( + logId = getLogId(ctx) + request = ssm.NewGetSSHKeyPairValueRequest() + ) + + defer func() { + if errRet != nil { + log.Printf("[CRITAL]%s api[%s] fail, request body [%s], reason[%s]\n", logId, request.GetAction(), request.ToJsonString(), errRet.Error()) + } + }() + + for k, v := range param { + if k == "SecretName" { + request.SecretName = v.(*string) + } + + if k == "SSHKeyId" { + request.SSHKeyId = v.(*string) + } + } + + ratelimit.Check(request.GetAction()) + + response, err := me.client.UseSsmClient().GetSSHKeyPairValue(request) + if err != nil { + errRet = err + return + } + + log.Printf("[DEBUG]%s api[%s] success, request body [%s], response body [%s]\n", logId, request.GetAction(), request.ToJsonString(), response.ToJsonString()) + + if response == nil { + return + } + + sshKeyPairValue = response.Response + return +} diff --git a/website/docs/d/ssm_rotation_detail.html.markdown b/website/docs/d/ssm_rotation_detail.html.markdown new file mode 100644 index 0000000000..0eca560fbb --- /dev/null +++ b/website/docs/d/ssm_rotation_detail.html.markdown @@ -0,0 +1,38 @@ +--- +subcategory: "Secrets Manager(SSM)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_ssm_rotation_detail" +sidebar_current: "docs-tencentcloud-datasource-ssm_rotation_detail" +description: |- + Use this data source to query detailed information of ssm rotation_detail +--- + +# tencentcloud_ssm_rotation_detail + +Use this data source to query detailed information of ssm rotation_detail + +## Example Usage + +```hcl +data "tencentcloud_ssm_rotation_detail" "example" { + secret_name = "tf_example" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `secret_name` - (Required, String) Secret name. +* `result_output_file` - (Optional, String) Used to save results. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `enable_rotation` - Whether to allow rotation. +* `frequency` - The rotation frequency, in days, defaults to 1 day. +* `latest_rotate_time` - Time of last rotation. +* `next_rotate_begin_time` - The time to start the next rotation. + + diff --git a/website/docs/d/ssm_rotation_history.html.markdown b/website/docs/d/ssm_rotation_history.html.markdown new file mode 100644 index 0000000000..aeba022e23 --- /dev/null +++ b/website/docs/d/ssm_rotation_history.html.markdown @@ -0,0 +1,35 @@ +--- +subcategory: "Secrets Manager(SSM)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_ssm_rotation_history" +sidebar_current: "docs-tencentcloud-datasource-ssm_rotation_history" +description: |- + Use this data source to query detailed information of ssm rotation_history +--- + +# tencentcloud_ssm_rotation_history + +Use this data source to query detailed information of ssm rotation_history + +## Example Usage + +```hcl +data "tencentcloud_ssm_rotation_history" "example" { + secret_name = "keep_terraform" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `secret_name` - (Required, String) Secret name. +* `result_output_file` - (Optional, String) Used to save results. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `version_ids` - The number of version numbers. The maximum number of version numbers that can be displayed to users is 10. + + diff --git a/website/docs/d/ssm_service_status.html.markdown b/website/docs/d/ssm_service_status.html.markdown new file mode 100644 index 0000000000..effa7b06ab --- /dev/null +++ b/website/docs/d/ssm_service_status.html.markdown @@ -0,0 +1,34 @@ +--- +subcategory: "Secrets Manager(SSM)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_ssm_service_status" +sidebar_current: "docs-tencentcloud-datasource-ssm_service_status" +description: |- + Use this data source to query detailed information of ssm service_status +--- + +# tencentcloud_ssm_service_status + +Use this data source to query detailed information of ssm service_status + +## Example Usage + +```hcl +data "tencentcloud_ssm_service_status" "example" {} +``` + +## Argument Reference + +The following arguments are supported: + +* `result_output_file` - (Optional, String) Used to save results. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `access_key_escrow_enabled` - True means that the user can already use the key safe hosting function, false means that the user cannot use the key safe hosting function temporarily. +* `invalid_type` - Service unavailability type: 0-Not purchased, 1-Normal, 2-Service suspended due to arrears, 3-Resource release. +* `service_enabled` - True means the service has been activated, false means the service has not been activated yet. + + diff --git a/website/docs/d/ssm_ssh_key_pair_value.html.markdown b/website/docs/d/ssm_ssh_key_pair_value.html.markdown new file mode 100644 index 0000000000..deb4f4c1b8 --- /dev/null +++ b/website/docs/d/ssm_ssh_key_pair_value.html.markdown @@ -0,0 +1,59 @@ +--- +subcategory: "Secrets Manager(SSM)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_ssm_ssh_key_pair_value" +sidebar_current: "docs-tencentcloud-datasource-ssm_ssh_key_pair_value" +description: |- + Use this data source to query detailed information of ssm ssh_key_pair_value +--- + +# tencentcloud_ssm_ssh_key_pair_value + +Use this data source to query detailed information of ssm ssh_key_pair_value + +~> **NOTE:** Must set at least one of `secret_name` or `ssh_key_id`. + +## Example Usage + +```hcl +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + secret_name = "keep_terraform" + ssh_key_id = "skey-2ae2snwd" +} +``` + +### Or + +```hcl +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + secret_name = "keep_terraform" +} +``` + +### Or + +```hcl +data "tencentcloud_ssm_ssh_key_pair_value" "example" { + ssh_key_id = "skey-2ae2snwd" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `result_output_file` - (Optional, String) Used to save results. +* `secret_name` - (Optional, String) Secret name. +* `ssh_key_id` - (Optional, String) The key pair ID is the unique identifier of the key pair in the cloud server. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `private_key` - Private key plain text, encoded using base64. +* `project_id` - The project ID to which this key pair belongs. +* `public_key` - Public key plain text, encoded using base64. +* `ssh_key_description` - Description of the SSH key pair. Users can modify the description information of the key pair in the CVM console. +* `ssh_key_name` - SSH key name. + + diff --git a/website/docs/r/ssm_rotate_product_secret.html.markdown b/website/docs/r/ssm_rotate_product_secret.html.markdown new file mode 100644 index 0000000000..115b207d39 --- /dev/null +++ b/website/docs/r/ssm_rotate_product_secret.html.markdown @@ -0,0 +1,35 @@ +--- +subcategory: "Secrets Manager(SSM)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_ssm_rotate_product_secret" +sidebar_current: "docs-tencentcloud-resource-ssm_rotate_product_secret" +description: |- + Provides a resource to create a ssm rotate_product_secret +--- + +# tencentcloud_ssm_rotate_product_secret + +Provides a resource to create a ssm rotate_product_secret + +## Example Usage + +```hcl +resource "tencentcloud_ssm_rotate_product_secret" "example" { + secret_name = "tf_example" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `secret_name` - (Required, String, ForceNew) Secret name. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `id` - ID of the resource. + + + diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index 4234e93952..f31d226d38 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -2472,12 +2472,24 @@