Skip to content

Commit ec1ac7e

Browse files
Lyc-hengLyc-heng
andauthored
Add permanent access key details to Huawei Cloud collector and introduce a policy to flag keys unused for over one year (#90)
* fix:Add AK details to check the last usage time of the AK * feature:Add a new rule to check whether the AK last used time exceeds 365 days. --------- Co-authored-by: Lyc-heng <[email protected]>
1 parent 0a2efdc commit ec1ac7e

File tree

5 files changed

+50
-5
lines changed

5 files changed

+50
-5
lines changed

collector/hws/collector/iam/user.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ package iam
1818
import (
1919
"context"
2020

21+
"github.com/cloudrec/hws/collector"
2122
"github.com/core-sdk/constant"
2223
"github.com/core-sdk/log"
2324
"github.com/core-sdk/schema"
24-
"github.com/cloudrec/hws/collector"
2525
iam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3"
2626
"github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model"
2727
"go.uber.org/zap"
@@ -46,6 +46,7 @@ type UserDetail struct {
4646
User model.KeystoneListUsersResult
4747
UserAttribute *model.ShowUserResult
4848
Credentials *[]model.Credentials
49+
CredentialsDetail []*model.ShowCredential
4950
UserGroups []*UserGroup
5051
LoginProtects *model.LoginProtectResult
5152
DomainPasswordPolicy *model.PasswordPolicyResult
@@ -67,10 +68,12 @@ func GetUserDetail(ctx context.Context, service schema.ServiceInterface, res cha
6768
}
6869

6970
for _, user := range *response.Users {
71+
credentials, CredentialsDetail := listPermanentAccessKeys(ctx, cli, user.Id)
7072
res <- &UserDetail{
7173
User: user,
7274
UserAttribute: showUser(ctx, cli, user.Id),
73-
Credentials: listPermanentAccessKeys(ctx, cli, user.Id),
75+
Credentials: credentials,
76+
CredentialsDetail: CredentialsDetail,
7477
DomainPasswordPolicy: getDomainPasswordPolicy(ctx, cli, user.DomainId),
7578
LoginProtects: showUserLoginProtect(ctx, cli, user.Id),
7679
}
@@ -79,16 +82,34 @@ func GetUserDetail(ctx context.Context, service schema.ServiceInterface, res cha
7982
return nil
8083
}
8184

82-
func listPermanentAccessKeys(ctx context.Context, cli *iam.IamClient, id string) (credentials *[]model.Credentials) {
85+
func listPermanentAccessKeys(ctx context.Context, cli *iam.IamClient, id string) (*[]model.Credentials, []*model.ShowCredential) {
8386
request := &model.ListPermanentAccessKeysRequest{}
8487
request.UserId = &id
8588
response, err := cli.ListPermanentAccessKeys(request)
8689
if err != nil {
8790
log.CtxLogger(ctx).Warn("ListPermanentAccessKeys error", zap.Error(err))
88-
return
91+
return nil, nil
92+
}
93+
94+
var credentialsDetail []*model.ShowCredential
95+
for _, credential := range *response.Credentials{
96+
credentialDetail := showPermanentAccessKey(ctx, cli, credential.Access)
97+
credentialsDetail = append(credentialsDetail, credentialDetail)
98+
}
99+
100+
return response.Credentials, credentialsDetail
101+
}
102+
103+
func showPermanentAccessKey(ctx context.Context, cli *iam.IamClient, AccessKey string)(*model.ShowCredential){
104+
request := &model.ShowPermanentAccessKeyRequest{}
105+
request.AccessKey = AccessKey
106+
response, err := cli.ShowPermanentAccessKey(request)
107+
if err != nil {
108+
log.CtxLogger(ctx).Warn("ShowPermanentAccessKey error", zap.Error(err))
109+
return nil
89110
}
90111

91-
return response.Credentials
112+
return response.Credential
92113
}
93114

94115
func getDomainPasswordPolicy(ctx context.Context, cli *iam.IamClient, domainId string) *model.PasswordPolicyResult {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"CredentialsDetail":[{"last_use_time":"VTMl0siGdLtfvi2byXwFtNvIQNx","access":"MvwxL6lnop8WR6WtsVZL","create_time":"0WBWc4SEyXJWqxR9j9b0yUjf6MH","user_id":"UNZEMOqhFHvDLwqIcZ4QtGlJZc9zjbhX","description":"xjjNYokyCZ4Vl4Bm","status":"7zjqk6"},{"last_use_time":"7x1L62kp2gD0DwFV4AueALRKMnr","access":"dCGceTyJTRnTMekZ8Fpo","create_time":"9WOo0sPf8SEXLTfB3cVDN0Xuk28","user_id":"2225vUnkTMIDnRU9PQfkzEB8VqVzC9hF","description":"YumZGdop9gBpbZ7j","status":"13DbY9"}],"User":{"domain_id":"Wx5dWt6AvZpVW6rQc8waxZFneSz6QGxI","pwd_status":false,"name":"G6wxF7042rLQfNFjA","links":{"next":"","previous":"","self":"XYQMeoxznfPVQrSinZ7M0KiXujwAsXpPUEWJYQv2WNZC2F2F9DOZho3cpuLH1yZCKx2YWuvSwfRSgfUiX"},"password_expires_at":"","id":"xPHdIytYxkH9f9YRXovdGCwBb5WLPQTC","enabled":true},"LoginProtects":null,"UserAttribute":{"pwd_strength":"bhb3","create_time":"pwmwLYowO22PLXnbkkZQ6","last_login_time":"cT6oX2bqlK8zDV9O0AR","description":"","access_mode":"cM7F3Pn","areacode":"","enabled":true,"domain_id":"CfQHFZtWztUIbDIr4oyXCViCg2O8qLr4","pwd_status":false,"xuser_id":"","update_time":"2Twx4bZm9o8YvL4CtpKrr","phone":"w","is_domain_owner":false,"name":"kQ0jF4Gw4FHbLlk2i","links":{"next":"","previous":"","self":"Q26kmAZ0EhcwoSlbDRvDopIeOWptPfrdeqzgviXBvF0z26GlH2uB5QJPTckFjuwsFuY8Rw7Z9yQsPqFswKWhvAWEYtO"},"id":"InmZlvmRUGemZI7hR3S3KLaOUeoM3ksr","xuser_type":"","email":""},"DomainPasswordPolicy":{"password_not_username_or_invert":true,"password_char_combination":3,"password_validity_period":90,"minimum_password_age":0,"maximum_password_length":32,"password_requirements":"ml64zq0ePvNjzGepQ3UZBaop8FoMSh2QkBWPOWggRFDxaG3pwy8NOtHug4XoUZohb6uCLSArHJdC9CqTJTZgrSBfwtSKNLF0dVhYFNugJWGJs7iAKhJCY6LBgFrG","maximum_consecutive_identical_chars":0,"minimum_password_length":12,"number_of_recent_passwords_disallowed":4},"Credentials":[{"access":"gV2kBLXcYCmavOfr0Z1g","create_time":"zy7PqjCt8fPonn4i0gTD9e7ZD4H","user_id":"iJlQDdDIeGCmXQ3VwsSLVjo7nLOoTtCR","description":"IKXtmIEUoz9WvOzS","status":"U80yx7"},{"access":"yG0nDtyNpaOcxP1v8ftA","create_time":"hUmGKEC4fX4RamUfloZdvP9zNDG","user_id":"4TBChHgUaTxg211T8TGapK5W89ab1yGd","description":"xyVfA23aVOarzbyV","status":"YfHZzU"}],"UserGroups":null}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"advice":null,"categoryList":["身份安全"],"code":"HUAWEI_CLOUD_IAM User_202511112036_1023138","context":null,"description":"RAM用户长期未使用的AccessKey仍具有效权限,若被泄露或滥用可能导致非授权访问、数据泄露或资源滥用,且违反凭证生命周期管理安全原则。","level":"Medium","link":null,"linkedDataList":null,"name":"IAM 用户 AK 超过一年未使用","platform":"HUAWEI_CLOUD","resourceType":"IAM User"}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package hws_ak_no_use_for_one_year_109
2+
import rego.v1
3+
4+
now_ns := time.now_ns()
5+
6+
default risk := false
7+
8+
risk if {
9+
count(ak_no_use_for_one_year) > 0
10+
}
11+
12+
user_name := input.UserAttribute.name
13+
user_id := input.UserAttribute.domain_id
14+
15+
ak_no_use_for_one_year contains p if {
16+
some p in input.CredentialsDetail
17+
p.status == "active"
18+
last_used_date_ns := time.parse_rfc3339_ns(p.last_use_time)
19+
tmp := time.add_date(last_used_date_ns, 0, 0, 365)
20+
tmp < now_ns
21+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[]

0 commit comments

Comments
 (0)