diff --git a/.changelog/2857.txt b/.changelog/2857.txt new file mode 100644 index 0000000000..cb5f4a4b0d --- /dev/null +++ b/.changelog/2857.txt @@ -0,0 +1,3 @@ +```release-note:new-data-source +tencentcloud_audit_events +``` diff --git a/.github/workflows/fmt.yml b/.github/workflows/fmt.yml index fb2c1839e7..89def3deae 100644 --- a/.github/workflows/fmt.yml +++ b/.github/workflows/fmt.yml @@ -23,7 +23,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v1 with: - go-version: 1.18 + go-version: 1.20 # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v3 diff --git a/tencentcloud/provider.go b/tencentcloud/provider.go index 9842ec57e1..c4cd57710e 100644 --- a/tencentcloud/provider.go +++ b/tencentcloud/provider.go @@ -724,6 +724,7 @@ func Provider() *schema.Provider { "tencentcloud_audit_cos_regions": audit.DataSourceTencentCloudAuditCosRegions(), "tencentcloud_audit_key_alias": audit.DataSourceTencentCloudAuditKeyAlias(), "tencentcloud_audits": audit.DataSourceTencentCloudAudits(), + "tencentcloud_audit_events": audit.DataSourceTencentCloudAuditEvents(), "tencentcloud_cynosdb_clusters": cynosdb.DataSourceTencentCloudCynosdbClusters(), "tencentcloud_cynosdb_instances": cynosdb.DataSourceTencentCloudCynosdbInstances(), "tencentcloud_cynosdb_zone_config": cynosdb.DataSourceTencentCloudCynosdbZoneConfig(), diff --git a/tencentcloud/provider.md b/tencentcloud/provider.md index 40aad027be..2714a3d8c6 100644 --- a/tencentcloud/provider.md +++ b/tencentcloud/provider.md @@ -155,6 +155,7 @@ Cloud Audit(Audit) tencentcloud_audit_cos_regions tencentcloud_audit_key_alias tencentcloud_audits + tencentcloud_audit_events Resource tencentcloud_audit diff --git a/tencentcloud/services/audit/data_source_tc_audit_events.go b/tencentcloud/services/audit/data_source_tc_audit_events.go new file mode 100644 index 0000000000..75cecdf827 --- /dev/null +++ b/tencentcloud/services/audit/data_source_tc_audit_events.go @@ -0,0 +1,338 @@ +package audit + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + cloudaudit "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudaudit/v20190319" + tccommon "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/common" + "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper" +) + +func DataSourceTencentCloudAuditEvents() *schema.Resource { + return &schema.Resource{ + Read: dataSourceTencentCloudAuditEventsRead, + Schema: map[string]*schema.Schema{ + "start_time": { + Type: schema.TypeInt, + Required: true, + Description: "Start timestamp in seconds (cannot be 90 days after the current time).", + }, + + "end_time": { + Type: schema.TypeInt, + Required: true, + Description: "End timestamp in seconds (the time range for query is less than 30 days).", + }, + + "max_results": { + Type: schema.TypeInt, + Optional: true, + Description: "Max number of returned logs (up to 50).", + }, + + "lookup_attributes": { + Type: schema.TypeList, + Optional: true, + Description: "Search condition. Valid values: `RequestId`, `EventName`, `ActionType` (write/read), `PrincipalId` (sub-account), `ResourceType`, `ResourceName`, `AccessKeyId`, `SensitiveAction`, `ApiErrorCode`, `CamErrorCode`, and `Tags` (Format of AttributeValue: [{\"key\":\"*\",\"value\":\"*\"}]).", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "attribute_key": { + Type: schema.TypeString, + Required: true, + Description: "Valid values: RequestId, EventName, ReadOnly, Username, ResourceType, ResourceName, AccessKeyId, and EventId\nNote: `null` may be returned for this field, indicating that no valid values can be obtained.", + }, + "attribute_value": { + Type: schema.TypeString, + Optional: true, + Description: "Value of `AttributeValue`\nNote: `null` may be returned for this field, indicating that no valid values can be obtained.", + }, + }, + }, + }, + + "is_return_location": { + Type: schema.TypeInt, + Optional: true, + Description: "Whether to return the IP location. `1`: yes, `0`: no.", + }, + + "events": { + Type: schema.TypeList, + Computed: true, + Description: "Logset. Note: `null` may be returned for this field, indicating that no valid values can be obtained.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "event_id": { + Type: schema.TypeString, + Optional: true, + Description: "Log ID.", + }, + "username": { + Type: schema.TypeString, + Optional: true, + Description: "Username.", + }, + "event_time": { + Type: schema.TypeString, + Optional: true, + Description: "Event Time.", + }, + "cloud_audit_event": { + Type: schema.TypeString, + Optional: true, + Description: "Log details.", + }, + "resource_type_cn": { + Type: schema.TypeString, + Optional: true, + Description: "Description of resource type in Chinese (please use this field as required; if you are using other languages, ignore this field).", + }, + "error_code": { + Type: schema.TypeInt, + Optional: true, + Description: "Authentication error code.", + }, + "event_name": { + Type: schema.TypeString, + Optional: true, + Description: "Event name.", + }, + "secret_id": { + Type: schema.TypeString, + Optional: true, + Description: "Certificate ID\nNote: `null` may be returned for this field, indicating that no valid values can be obtained.", + }, + "event_source": { + Type: schema.TypeString, + Optional: true, + Description: "Request source.", + }, + "request_id": { + Type: schema.TypeString, + Optional: true, + Description: "Request ID.", + }, + "resource_region": { + Type: schema.TypeString, + Optional: true, + Description: "Resource region.", + }, + "account_id": { + Type: schema.TypeInt, + Optional: true, + Description: "Root account ID.", + }, + "source_ip_address": { + Type: schema.TypeString, + Optional: true, + Description: "Source IP\nNote: `null` may be returned for this field, indicating that no valid values can be obtained.", + }, + "event_name_cn": { + Type: schema.TypeString, + Optional: true, + Description: "Description of event name in Chinese (please use this field as required; if you are using other languages, ignore this field).", + }, + "resources": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: "Resource pair.", + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "resource_type": { + Type: schema.TypeString, + Optional: true, + Description: "Resource type.", + }, + "resource_name": { + Type: schema.TypeString, + Optional: true, + Description: "Resource name\nNote: `null` may be returned for this field, indicating that no valid values can be obtained.", + }, + }, + }, + }, + "event_region": { + Type: schema.TypeString, + Optional: true, + Description: "Event region.", + }, + "location": { + Type: schema.TypeString, + Optional: true, + Description: "IP location.", + }, + }, + }, + }, + + "result_output_file": { + Type: schema.TypeString, + Optional: true, + Description: "Used to save results.", + }, + }, + } +} + +func dataSourceTencentCloudAuditEventsRead(d *schema.ResourceData, meta interface{}) error { + defer tccommon.LogElapsed("data_source.tencentcloud_audit_event.read")() + defer tccommon.InconsistentCheck(d, meta)() + + logId := tccommon.GetLogId(nil) + ctx := tccommon.NewResourceLifeCycleHandleFuncContext(context.Background(), logId, d, meta) + + service := AuditService{client: meta.(tccommon.ProviderMeta).GetAPIV3Conn()} + + paramMap := make(map[string]interface{}) + + if v, ok := d.GetOkExists("max_results"); ok { + paramMap["MaxResults"] = helper.IntUint64(v.(int)) + } + + if v, ok := d.GetOkExists("start_time"); ok { + paramMap["StartTime"] = helper.IntUint64(v.(int)) + } + + if v, ok := d.GetOkExists("end_time"); ok { + paramMap["EndTime"] = helper.IntUint64(v.(int)) + } + + if v, ok := d.GetOk("lookup_attributes"); ok { + lookupAttributesSet := v.([]interface{}) + tmpSet := make([]*cloudaudit.LookupAttribute, 0, len(lookupAttributesSet)) + for _, item := range lookupAttributesSet { + lookupAttributesMap := item.(map[string]interface{}) + lookupAttribute := cloudaudit.LookupAttribute{} + if v, ok := lookupAttributesMap["attribute_key"]; ok { + lookupAttribute.AttributeKey = helper.String(v.(string)) + } + if v, ok := lookupAttributesMap["attribute_value"]; ok { + lookupAttribute.AttributeValue = helper.String(v.(string)) + } + tmpSet = append(tmpSet, &lookupAttribute) + } + paramMap["LookupAttributes"] = tmpSet + } + + if v, ok := d.GetOkExists("is_return_location"); ok { + paramMap["IsReturnLocation"] = helper.IntUint64(v.(int)) + } + + var respData []*cloudaudit.Event + err := resource.Retry(tccommon.ReadRetryTimeout, func() *resource.RetryError { + result, e := service.DescribeAuditEventByFilter(ctx, paramMap) + if e != nil { + return tccommon.RetryError(e) + } + respData = result + return nil + }) + if err != nil { + return err + } + + ids := make([]string, 0, len(respData)) + eventsList := make([]map[string]interface{}, 0, len(respData)) + if respData != nil { + for _, events := range respData { + eventsMap := map[string]interface{}{} + println(*events.EventId) + if events.EventId != nil { + eventsMap["event_id"] = events.EventId + } + + if events.Username != nil { + eventsMap["username"] = events.Username + } + + if events.EventTime != nil { + eventsMap["event_time"] = events.EventTime + } + + if events.CloudAuditEvent != nil { + eventsMap["cloud_audit_event"] = events.CloudAuditEvent + } + + if events.ResourceTypeCn != nil { + eventsMap["resource_type_cn"] = events.ResourceTypeCn + } + + if events.ErrorCode != nil { + eventsMap["error_code"] = events.ErrorCode + } + + if events.EventName != nil { + eventsMap["event_name"] = events.EventName + } + + if events.SecretId != nil { + eventsMap["secret_id"] = events.SecretId + } + + if events.EventSource != nil { + eventsMap["event_source"] = events.EventSource + } + + if events.RequestID != nil { + eventsMap["request_id"] = events.RequestID + } + + if events.ResourceRegion != nil { + eventsMap["resource_region"] = events.ResourceRegion + } + + if events.AccountID != nil { + eventsMap["account_id"] = events.AccountID + } + + if events.SourceIPAddress != nil { + eventsMap["source_ip_address"] = events.SourceIPAddress + } + + if events.EventNameCn != nil { + eventsMap["event_name_cn"] = events.EventNameCn + } + + resourcesMap := map[string]interface{}{} + + if events.Resources != nil { + if events.Resources.ResourceType != nil { + resourcesMap["resource_type"] = events.Resources.ResourceType + } + + if events.Resources.ResourceName != nil { + resourcesMap["resource_name"] = events.Resources.ResourceName + } + + eventsMap["resources"] = []interface{}{resourcesMap} + } + + if events.EventRegion != nil { + eventsMap["event_region"] = events.EventRegion + } + + if events.Location != nil { + eventsMap["location"] = events.Location + } + + eventsList = append(eventsList, eventsMap) + ids = append(ids, *events.EventId) + } + + _ = d.Set("events", eventsList) + } + + d.SetId(helper.DataResourceIdsHash(ids)) + + output, ok := d.GetOk("result_output_file") + if ok && output.(string) != "" { + if e := tccommon.WriteToFile(output.(string), eventsList); e != nil { + return e + } + } + + return nil +} diff --git a/tencentcloud/services/audit/data_source_tc_audit_events.md b/tencentcloud/services/audit/data_source_tc_audit_events.md new file mode 100644 index 0000000000..e20b5502a4 --- /dev/null +++ b/tencentcloud/services/audit/data_source_tc_audit_events.md @@ -0,0 +1,27 @@ +Use this data source to query the events list supported by the audit. + +Example Usage +```hcl +data "tencentcloud_audit_events" "events" { + start_time = "1727433841" + end_time = "1727437441" + max_results = 50 + + lookup_attributes { + attribute_key = "ResourceType" + attribute_value = "cvm" + } + + lookup_attributes { + attribute_key = "OnlyRecordNotSeen" + attribute_value = "0" + } + + lookup_attributes { + attribute_key = "EventPlatform" + attribute_value = "0" + } + + is_return_location = 1 +} +``` \ No newline at end of file diff --git a/tencentcloud/services/audit/data_source_tc_audit_events_test.go b/tencentcloud/services/audit/data_source_tc_audit_events_test.go new file mode 100644 index 0000000000..545020716e --- /dev/null +++ b/tencentcloud/services/audit/data_source_tc_audit_events_test.go @@ -0,0 +1,30 @@ +package audit_test + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + tcacctest "github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/acctest" +) + +func TestAccTencentCloudAuditEventDataSource_basic(t *testing.T) { + t.Parallel() + resource.Test(t, resource.TestCase{ + PreCheck: func() { + tcacctest.AccPreCheck(t) + }, + Providers: tcacctest.AccProviders, + Steps: []resource.TestStep{{ + Config: testAccAuditEventDataSource, + Check: resource.ComposeTestCheckFunc(tcacctest.AccCheckTencentCloudDataSourceID("data.tencentcloud_audit_event.audit_event")), + }}, + }) +} + +const testAccAuditEventDataSource = ` + +data "tencentcloud_audit_event" "audit_event" { + lookup_attributes = { + } +} +` diff --git a/tencentcloud/services/audit/service_tencentcloud_audit.go b/tencentcloud/services/audit/service_tencentcloud_audit.go index f020d403b0..45ff609d67 100644 --- a/tencentcloud/services/audit/service_tencentcloud_audit.go +++ b/tencentcloud/services/audit/service_tencentcloud_audit.go @@ -175,3 +175,54 @@ func (me *AuditService) DeleteAuditTrackById(ctx context.Context, trackId string return } + +func (me *AuditService) DescribeAuditEventByFilter(ctx context.Context, param map[string]interface{}) (ret []*audit.Event, errRet error) { + var ( + logId = tccommon.GetLogId(ctx) + request = audit.NewDescribeEventsRequest() + ) + + 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 == "MaxResults" { + request.MaxResults = v.(*uint64) + } + if k == "StartTime" { + request.StartTime = v.(*uint64) + } + if k == "EndTime" { + request.EndTime = v.(*uint64) + } + if k == "LookupAttributes" { + request.LookupAttributes = v.([]*audit.LookupAttribute) + } + if k == "IsReturnLocation" { + request.IsReturnLocation = v.(*uint64) + } + } + + ratelimit.Check(request.GetAction()) + + for { + response, err := me.client.UseAuditClient().DescribeEvents(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()) + + ret = append(ret, response.Response.Events...) + if *response.Response.ListOver == true { + break + } + + request.NextToken = response.Response.NextToken + } + + return +} diff --git a/website/docs/d/audit_events.html.markdown b/website/docs/d/audit_events.html.markdown new file mode 100644 index 0000000000..b4197d3a9e --- /dev/null +++ b/website/docs/d/audit_events.html.markdown @@ -0,0 +1,65 @@ +--- +subcategory: "Cloud Audit(Audit)" +layout: "tencentcloud" +page_title: "TencentCloud: tencentcloud_audit_events" +sidebar_current: "docs-tencentcloud-datasource-audit_events" +description: |- + Use this data source to query the events list supported by the audit. +--- + +# tencentcloud_audit_events + +Use this data source to query the events list supported by the audit. + +## Example Usage + +```hcl +data "tencentcloud_audit_events" "events" { + start_time = "1727433841" + end_time = "1727437441" + max_results = 50 + + lookup_attributes { + attribute_key = "ResourceType" + attribute_value = "cvm" + } + + lookup_attributes { + attribute_key = "OnlyRecordNotSeen" + attribute_value = "0" + } + + lookup_attributes { + attribute_key = "EventPlatform" + attribute_value = "0" + } + + is_return_location = 1 +} +``` + +## Argument Reference + +The following arguments are supported: + +* `end_time` - (Required, Int) End timestamp in seconds (the time range for query is less than 30 days). +* `start_time` - (Required, Int) Start timestamp in seconds (cannot be 90 days after the current time). +* `is_return_location` - (Optional, Int) Whether to return the IP location. `1`: yes, `0`: no. +* `lookup_attributes` - (Optional, List) Search condition. Valid values: `RequestId`, `EventName`, `ActionType` (write/read), `PrincipalId` (sub-account), `ResourceType`, `ResourceName`, `AccessKeyId`, `SensitiveAction`, `ApiErrorCode`, `CamErrorCode`, and `Tags` (Format of AttributeValue: [{"key":"*","value":"*"}]). +* `max_results` - (Optional, Int) Max number of returned logs (up to 50). +* `result_output_file` - (Optional, String) Used to save results. + +The `lookup_attributes` object supports the following: + +* `attribute_key` - (Required, String) Valid values: RequestId, EventName, ReadOnly, Username, ResourceType, ResourceName, AccessKeyId, and EventId +Note: `null` may be returned for this field, indicating that no valid values can be obtained. +* `attribute_value` - (Optional, String) Value of `AttributeValue` +Note: `null` may be returned for this field, indicating that no valid values can be obtained. + +## Attributes Reference + +In addition to all arguments above, the following attributes are exported: + +* `events` - Logset. Note: `null` may be returned for this field, indicating that no valid values can be obtained. + + diff --git a/website/tencentcloud.erb b/website/tencentcloud.erb index a5bb3a93dc..b8fae6e665 100644 --- a/website/tencentcloud.erb +++ b/website/tencentcloud.erb @@ -827,6 +827,9 @@
  • tencentcloud_audit_cos_regions
  • +
  • + tencentcloud_audit_events +
  • tencentcloud_audit_key_alias