Skip to content

Commit bea7f20

Browse files
authored
resource scanning added to obtain creator code (#2519)
* resource scanning added to obtain creator code * add get resource creator account info code * add resource create action * update query rule * update create time parse code
1 parent b9a8fa4 commit bea7f20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+8028
-66
lines changed

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ require (
4646
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/clb v1.0.847
4747
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cloudaudit v1.0.544
4848
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cls v1.0.711
49-
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.847
49+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.856
5050
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.624
5151
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cwp v1.0.762
5252
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cynosdb v1.0.692
@@ -110,6 +110,7 @@ require (
110110
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cdwpg v1.0.772
111111
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dasb v1.0.798
112112
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/oceanus v1.0.831
113+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/billing v1.0.856
113114
github.com/wI2L/jsondiff v0.3.0
114115
k8s.io/apimachinery v0.22.4
115116
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bi v1.0.770 h1:5FWt9F+a
834834
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bi v1.0.770/go.mod h1:zuWcAJVIXbHbOR7i6SKK0wNlvPLt5Su4ijOZGMJbUi8=
835835
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bi v1.0.824 h1:DVKvZ6h+qd7tadUrCjVAkCCmE3TsbK2ZmwGd3AJcpWc=
836836
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/bi v1.0.824/go.mod h1:DvBpDX/qdJG4KKLeULmRvhAjPYiw8za0HeTSu2y/lFw=
837+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/billing v1.0.856 h1:zJBb69FBBNZko4PbDScqj9wogPatzNYEXAJ862IBoMQ=
838+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/billing v1.0.856/go.mod h1:P+VGibeVh8pW4N85x9ee0xzXsZoT9jzjHYD8GaAiyG4=
837839
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760 h1:Ky9dRsTL2HXKWUrTFpQFZWQ1TrM+o+P35kczR7thalo=
838840
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam v1.0.760/go.mod h1:AAfdrxknvUedvigxbbzKQLxN+1EG5NPbytpiqmfuFvU=
839841
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cat v1.0.760 h1:oGY4IigfIw0iQKh3/cOY29KBeEeFbvJft69e0beyfdI=
@@ -954,6 +956,8 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.845 h1:fiiV
954956
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.845/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
955957
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.847 h1:ITZmxAWfbr5yikJ4T30yVYMW3jpa/oTmNbPnw/h1Vq0=
956958
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.847/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
959+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.856 h1:4PaaKxPjh0dmRzzz0CRZSZlbvzQIPcg4TE1Ibz0Cdlk=
960+
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.856/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
957961
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.624 h1:nEZqsoqt1pEoaP9JjkHQy3/H00suCfzlHW1qOm2nYD8=
958962
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cvm v1.0.624/go.mod h1:+TXSVyeKwt1IhZRqKPbTREteBcP+K07Q846/ilNzLWA=
959963
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cwp v1.0.762 h1:2egy69SP/wPsmnfozcQVZ6tUY6F6N/TpEe/7xtXrc/8=

tencentcloud/common/cloud_common.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package common
2+
3+
import (
4+
"encoding/json"
5+
cls "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cls/v20201016"
6+
"log"
7+
"strconv"
8+
"strings"
9+
"time"
10+
11+
cam "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/cam/v20190116"
12+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/connectivity"
13+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/internal/helper"
14+
)
15+
16+
const (
17+
// DefaultSearchLogStartTimestamp sync logs start time 2023-11-07 16:41:00
18+
DefaultSearchLogStartTimestamp = 1699346460000
19+
20+
DefaultTopicId = "aef50d54-b17d-4782-8618-a7873203ec29"
21+
22+
QueryGrammarRule = " AND "
23+
)
24+
25+
// ResourceAccountInfo 资源账户信息
26+
type ResourceAccountInfo struct {
27+
ResourceType string // 资源类型
28+
ResourceName string // 资源名称
29+
AccountId string // 主账号ID
30+
PrincipalId string // 用户ID
31+
UserName string // 用户名
32+
}
33+
34+
// GetResourceCreatorAccountInfo get resource creator user info
35+
func GetResourceCreatorAccountInfo(client *connectivity.TencentCloudClient, resourceCreateAction string, resources []*ResourceInstance) map[string]*ResourceAccountInfo {
36+
resourceIdToSubAccountInfoMap := make(map[string]*ResourceAccountInfo)
37+
if resourceCreateAction == "" {
38+
return resourceIdToSubAccountInfoMap
39+
}
40+
41+
request := cls.NewSearchLogRequest()
42+
request.From = helper.IntInt64(DefaultSearchLogStartTimestamp)
43+
request.To = helper.Int64(CurrentTimeMillisecond())
44+
request.TopicId = helper.String(DefaultTopicId)
45+
46+
for _, r := range resources {
47+
query := resourceCreateAction + QueryGrammarRule
48+
if r.Id != "" {
49+
query = query + r.Id
50+
} else if r.Name != "" {
51+
query = query + r.Name
52+
} else {
53+
continue
54+
}
55+
request.Query = helper.String(query)
56+
57+
response, err := client.UseClsClient().SearchLog(request)
58+
if err != nil {
59+
log.Printf("[CRITAL] search resource[%v] log data error: %v", r.Id, err.Error())
60+
return resourceIdToSubAccountInfoMap
61+
}
62+
if response == nil || response.Response == nil {
63+
log.Printf("[CRITAL] search resource[%v] log data response is nil", r.Id)
64+
return resourceIdToSubAccountInfoMap
65+
}
66+
if len(response.Response.Results) == 0 {
67+
log.Printf("[CRITAL] search resource[%v] log data response results is empty", r.Id)
68+
return resourceIdToSubAccountInfoMap
69+
}
70+
71+
result := response.Response.Results[0]
72+
if result != nil {
73+
var jsonData string
74+
if len(*result.LogJson) > 2 {
75+
jsonData = *result.LogJson
76+
} else if len(*result.RawLog) > 2 {
77+
jsonData = *result.RawLog
78+
} else {
79+
continue
80+
}
81+
82+
resourceAccountInfo := ParseLogJsonData(jsonData)
83+
if resourceAccountInfo.PrincipalId == resourceAccountInfo.UserName &&
84+
resourceAccountInfo.PrincipalId != resourceAccountInfo.AccountId {
85+
userName := GetSubAccountUserName(client, resourceAccountInfo.PrincipalId)
86+
resourceAccountInfo.UserName = userName
87+
}
88+
resourceIdToSubAccountInfoMap[r.Id] = resourceAccountInfo
89+
}
90+
}
91+
92+
return resourceIdToSubAccountInfoMap
93+
}
94+
95+
// GetSubAccountUserName get sub account user name
96+
func GetSubAccountUserName(client *connectivity.TencentCloudClient, uin string) string {
97+
uinNum, err := strconv.ParseUint(uin, 10, 64)
98+
if err != nil {
99+
log.Printf("[CRITAL] parse uin[%v] to uint64 type error: %v", uin, err.Error())
100+
return ""
101+
}
102+
103+
request := cam.NewDescribeSubAccountsRequest()
104+
105+
uinArray := []*uint64{helper.Uint64(uinNum)}
106+
request.FilterSubAccountUin = uinArray
107+
108+
response, err := client.UseCamClient().DescribeSubAccounts(request)
109+
if err != nil {
110+
log.Printf("[CRITAL] get sub account[%v] data error: %v", uin, err.Error())
111+
return ""
112+
}
113+
if response == nil || response.Response == nil {
114+
log.Printf("[CRITAL] get sub account[%v] data response is nil", uin)
115+
return ""
116+
}
117+
118+
name := response.Response.SubAccounts[0].Name
119+
return *name
120+
}
121+
122+
// CurrentTimeMillisecond get the current millisecond timestamp
123+
func CurrentTimeMillisecond() int64 {
124+
return time.Now().UnixNano() / int64(time.Millisecond)
125+
}
126+
127+
func ParseLogJsonData(jsonData string) *ResourceAccountInfo {
128+
if jsonData == "" {
129+
return nil
130+
}
131+
132+
var data map[string]interface{}
133+
err := json.Unmarshal([]byte(jsonData), &data)
134+
if err != nil {
135+
log.Printf("[CRITAL] parse log json data[%v] error: %v", jsonData, err.Error())
136+
return nil
137+
}
138+
139+
resourceType := ""
140+
if v, ok := data["resourceType"]; ok {
141+
resourceType = v.(string)
142+
}
143+
resourceName := ""
144+
if v, ok := data["resourceName"]; ok {
145+
resourceName = v.(string)
146+
if resourceName != "" {
147+
resourceName = strings.Split(resourceName, "/")[0]
148+
}
149+
}
150+
accountId, principalId, userName := parseUserIdentityFields(data)
151+
152+
return &ResourceAccountInfo{
153+
ResourceType: resourceType,
154+
ResourceName: resourceName,
155+
AccountId: accountId,
156+
PrincipalId: principalId,
157+
UserName: userName,
158+
}
159+
}
160+
161+
func parseUserIdentityFields(data map[string]interface{}) (accountId, principalId, userName string) {
162+
if v, ok := data["userIdentity.accountId"]; ok {
163+
accountId = v.(string)
164+
}
165+
if v, ok := data["userIdentity.principalId"]; ok {
166+
principalId = v.(string)
167+
}
168+
if v, ok := data["userIdentity.userName"]; ok {
169+
userName = v.(string)
170+
}
171+
if v, ok := data["userIdentity"]; ok {
172+
switch v := v.(type) {
173+
case string:
174+
var userIdentity map[string]string
175+
err := json.Unmarshal([]byte(v), &userIdentity)
176+
if err == nil {
177+
accountId = userIdentity["accountId"]
178+
principalId = userIdentity["principalId"]
179+
userName = userIdentity["userName"]
180+
}
181+
}
182+
}
183+
return
184+
}

tencentcloud/common/file_common.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ const (
1313
SweeperNonKeepResourceScanDir = "../../../tmp/non_keep_resource_scan/"
1414
)
1515

16-
var ResourceScanHeader = []string{"资源类型", "资源名称", "实例ID", "实例名称", "分类", "创建时长(天)"}
17-
var NonKeepResourceScanHeader = []string{"ResourceType", "ResourceName", "InstanceId", "InstanceName"}
16+
var ResourceScanHeader = []string{"资源类型", "资源名称", "实例ID", "实例名称", "分类", "创建时长(天)", "创建者用户ID", "创建者用户名"}
17+
var NonKeepResourceScanHeader = []string{"ResourceType", "ResourceName", "InstanceId", "InstanceName", "PrincipalId", "UserName"}
1818

1919
// WriteCsvFileData write data to csv file
2020
func WriteCsvFileData(dirPath string, header []string, data [][]string) error {

tencentcloud/common/resource_scan.go

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"regexp"
77
"strconv"
88
"time"
9+
10+
"github.com/tencentcloudstack/terraform-provider-tencentcloud/tencentcloud/connectivity"
911
)
1012

1113
const (
@@ -27,14 +29,16 @@ type ResourceInstance struct {
2729
DefaultKeep bool
2830
}
2931

30-
func ProcessScanCloudResources(resources, nonKeepResources []*ResourceInstance, resourceType, resourceName string) {
31-
ProcessResources(resources, resourceType, resourceName)
32+
func ProcessScanCloudResources(client *connectivity.TencentCloudClient, resources, nonKeepResources []*ResourceInstance, resourceCreateAction string) {
33+
ProcessResources(client, resources, resourceCreateAction)
3234

33-
ProcessNonKeepResources(nonKeepResources, resourceType, resourceName)
35+
ProcessNonKeepResources(client, nonKeepResources, resourceCreateAction)
3436
}
3537

3638
// ProcessResources Process all scanned cloud resources
37-
func ProcessResources(resources []*ResourceInstance, resourceType, resourceName string) {
39+
func ProcessResources(client *connectivity.TencentCloudClient, resources []*ResourceInstance, resourceCreateAction string) {
40+
resourceIdToSubAccountInfoMap := GetResourceCreatorAccountInfo(client, resourceCreateAction, resources)
41+
3842
data := make([][]string, len(resources))
3943
for i, r := range resources {
4044
isResourceKeep := CheckResourceNameKeep(r.Name)
@@ -48,13 +52,24 @@ func ProcessResources(resources []*ResourceInstance, resourceType, resourceName
4852
log.Printf("[CRITAL] compute resource creation duration error: %v", err.Error())
4953
}
5054

55+
var resourceType, resourceName, principalId, userName string
56+
creatorAccountInfo := resourceIdToSubAccountInfoMap[r.Id]
57+
if creatorAccountInfo != nil {
58+
resourceType = creatorAccountInfo.ResourceType
59+
resourceName = creatorAccountInfo.ResourceName
60+
principalId = creatorAccountInfo.PrincipalId
61+
userName = creatorAccountInfo.UserName
62+
}
63+
5164
data[i] = []string{
5265
resourceType,
5366
resourceName,
5467
r.Id,
5568
r.Name,
5669
isResourceKeep,
5770
creationDuration,
71+
principalId,
72+
userName,
5873
}
5974
}
6075
err := WriteCsvFileData(SweeperResourceScanDir, ResourceScanHeader, data)
@@ -64,14 +79,27 @@ func ProcessResources(resources []*ResourceInstance, resourceType, resourceName
6479
}
6580

6681
// ProcessNonKeepResources Processing scanned non-keep cloud resources
67-
func ProcessNonKeepResources(nonKeepResources []*ResourceInstance, resourceType, resourceName string) {
82+
func ProcessNonKeepResources(client *connectivity.TencentCloudClient, nonKeepResources []*ResourceInstance, resourceCreateAction string) {
83+
resourceIdToSubAccountInfoMap := GetResourceCreatorAccountInfo(client, resourceCreateAction, nonKeepResources)
84+
6885
data := make([][]string, len(nonKeepResources))
6986
for i, r := range nonKeepResources {
87+
var resourceType, resourceName, principalId, userName string
88+
creatorAccountInfo := resourceIdToSubAccountInfoMap[r.Id]
89+
if creatorAccountInfo != nil {
90+
resourceType = creatorAccountInfo.ResourceType
91+
resourceName = creatorAccountInfo.ResourceName
92+
principalId = creatorAccountInfo.PrincipalId
93+
userName = creatorAccountInfo.UserName
94+
}
95+
7096
data[i] = []string{
7197
resourceType,
7298
resourceName,
7399
r.Id,
74100
r.Name,
101+
principalId,
102+
userName,
75103
}
76104
}
77105
err := WriteCsvFileData(SweeperNonKeepResourceScanDir, NonKeepResourceScanHeader, data)
@@ -133,7 +161,7 @@ func ParsedTime(createTime string) (*time.Time, error) {
133161
} else {
134162
// try parsing input strings using different time formats
135163
for _, format := range TimeFormats {
136-
parsedTime, err = time.Parse(format, createTime)
164+
parsedTime, err = time.ParseInLocation(format, createTime, time.Local)
137165
if err == nil {
138166
break
139167
}

tencentcloud/connectivity/client.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"strconv"
99
"time"
1010

11+
billing "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/billing/v20180709"
1112
dasb "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dasb/v20191018"
1213

1314
oceanus "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/oceanus/v20190422"
@@ -199,6 +200,7 @@ type TencentCloudClient struct {
199200
trocketConn *trocket.Client
200201
biConn *bi.Client
201202
cdwpgConn *cdwpg.Client
203+
billingConn *billing.Client
202204
//internal version: replace client begin, please do not modify this annotation and refrain from inserting any code between the beginning and end lines of the annotation.
203205
//internal version: replace client end, please do not modify this annotation and refrain from inserting any code between the beginning and end lines of the annotation.
204206
}
@@ -1376,6 +1378,20 @@ func (me *TencentCloudClient) UseCdwpgClient() *cdwpg.Client {
13761378
return me.cdwpgConn
13771379
}
13781380

1381+
// UseBillingClient returns billing client for service
1382+
func (me *TencentCloudClient) UseBillingClient() *billing.Client {
1383+
if me.billingConn != nil {
1384+
return me.billingConn
1385+
}
1386+
1387+
cpf := me.NewClientProfile(300)
1388+
cpf.Language = "zh-CN"
1389+
me.billingConn, _ = billing.NewClient(me.Credential, me.Region, cpf)
1390+
me.billingConn.WithHttpTransport(&LogRoundTripper{})
1391+
1392+
return me.billingConn
1393+
}
1394+
13791395
//internal version: replace useClient begin, please do not modify this annotation and refrain from inserting any code between the beginning and end lines of the annotation.
13801396
//internal version: replace useClient end, please do not modify this annotation and refrain from inserting any code between the beginning and end lines of the annotation.
13811397

tencentcloud/services/as/resource_tc_as_attachment_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ func testSweepAsAttachment(r string) error {
2828
logId := tccommon.GetLogId(tccommon.ContextNil)
2929
ctx := context.WithValue(context.TODO(), tccommon.LogIdKey, logId)
3030
cli, _ := tcacctest.SharedClientForRegion(r)
31-
asService := svcas.NewAsService(cli.(tccommon.ProviderMeta).GetAPIV3Conn())
31+
client := cli.(tccommon.ProviderMeta).GetAPIV3Conn()
32+
asService := svcas.NewAsService(client)
3233

3334
scalingGroups, err := asService.DescribeAutoScalingGroupByFilter(ctx, "", "", "", nil)
3435
if err != nil {
@@ -50,7 +51,7 @@ func testSweepAsAttachment(r string) error {
5051
CreatTime: *v.CreatedTime,
5152
})
5253
}
53-
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "as", "attachment")
54+
tccommon.ProcessScanCloudResources(client, resources, nonKeepResources, "CreateAutoScalingGroup")
5455

5556
for _, v := range scalingGroups {
5657
scalingGroupId := *v.AutoScalingGroupId

tencentcloud/services/cam/resource_tc_cam_group_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func init() {
5050
CreatTime: *v.CreateTime,
5151
})
5252
}
53-
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "cam", "group")
53+
tccommon.ProcessScanCloudResources(client, resources, nonKeepResources, "CreateGroup")
5454

5555
for _, v := range groups {
5656
name := *v.GroupName

tencentcloud/services/cbs/resource_tc_cbs_storage_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ func init() {
4646
CreatTime: *v.CreateTime,
4747
})
4848
}
49-
tccommon.ProcessScanCloudResources(resources, nonKeepResources, "cbs", "storage")
49+
tccommon.ProcessScanCloudResources(client, resources, nonKeepResources, "CreateDisks")
5050

5151
for i := range disks {
5252
disk := disks[i]

0 commit comments

Comments
 (0)