From 95521191038850c66bef75ed91a3430f7e0519ea Mon Sep 17 00:00:00 2001 From: Lyc-heng Date: Tue, 11 Nov 2025 20:51:01 +0800 Subject: [PATCH 1/2] fix:Add AK details to check the last usage time of the AK --- collector/hws/collector/iam/user.go | 31 ++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/collector/hws/collector/iam/user.go b/collector/hws/collector/iam/user.go index 59c0d9db..fbc2debf 100644 --- a/collector/hws/collector/iam/user.go +++ b/collector/hws/collector/iam/user.go @@ -18,10 +18,10 @@ package iam import ( "context" + "github.com/cloudrec/hws/collector" "github.com/core-sdk/constant" "github.com/core-sdk/log" "github.com/core-sdk/schema" - "github.com/cloudrec/hws/collector" iam "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3" "github.com/huaweicloud/huaweicloud-sdk-go-v3/services/iam/v3/model" "go.uber.org/zap" @@ -46,6 +46,7 @@ type UserDetail struct { User model.KeystoneListUsersResult UserAttribute *model.ShowUserResult Credentials *[]model.Credentials + CredentialsDetail []*model.ShowCredential UserGroups []*UserGroup LoginProtects *model.LoginProtectResult DomainPasswordPolicy *model.PasswordPolicyResult @@ -67,10 +68,12 @@ func GetUserDetail(ctx context.Context, service schema.ServiceInterface, res cha } for _, user := range *response.Users { + credentials, CredentialsDetail := listPermanentAccessKeys(ctx, cli, user.Id) res <- &UserDetail{ User: user, UserAttribute: showUser(ctx, cli, user.Id), - Credentials: listPermanentAccessKeys(ctx, cli, user.Id), + Credentials: credentials, + CredentialsDetail: CredentialsDetail, DomainPasswordPolicy: getDomainPasswordPolicy(ctx, cli, user.DomainId), LoginProtects: showUserLoginProtect(ctx, cli, user.Id), } @@ -79,16 +82,34 @@ func GetUserDetail(ctx context.Context, service schema.ServiceInterface, res cha return nil } -func listPermanentAccessKeys(ctx context.Context, cli *iam.IamClient, id string) (credentials *[]model.Credentials) { +func listPermanentAccessKeys(ctx context.Context, cli *iam.IamClient, id string) (*[]model.Credentials, []*model.ShowCredential) { request := &model.ListPermanentAccessKeysRequest{} request.UserId = &id response, err := cli.ListPermanentAccessKeys(request) if err != nil { log.CtxLogger(ctx).Warn("ListPermanentAccessKeys error", zap.Error(err)) - return + return nil, nil + } + + var credentialsDetail []*model.ShowCredential + for _, credential := range *response.Credentials{ + credentialDetail := showPermanentAccessKey(ctx, cli, credential.Access) + credentialsDetail = append(credentialsDetail, credentialDetail) + } + + return response.Credentials, credentialsDetail +} + +func showPermanentAccessKey(ctx context.Context, cli *iam.IamClient, AccessKey string)(*model.ShowCredential){ + request := &model.ShowPermanentAccessKeyRequest{} + request.AccessKey = AccessKey + response, err := cli.ShowPermanentAccessKey(request) + if err != nil { + log.CtxLogger(ctx).Warn("ShowPermanentAccessKey error", zap.Error(err)) + return nil } - return response.Credentials + return response.Credential } func getDomainPasswordPolicy(ctx context.Context, cli *iam.IamClient, domainId string) *model.PasswordPolicyResult { From eddf0d732aae03a3f0e4bbf91954038aa779db45 Mon Sep 17 00:00:00 2001 From: Lyc-heng Date: Tue, 11 Nov 2025 20:56:55 +0800 Subject: [PATCH 2/2] feature:Add a new rule to check whether the AK last used time exceeds 365 days. --- .../input.json | 1 + .../metadata.json | 1 + .../policy.rego | 21 +++++++++++++++++++ .../relation.json | 1 + 4 files changed, 24 insertions(+) create mode 100644 rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/input.json create mode 100644 rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/metadata.json create mode 100644 rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/policy.rego create mode 100644 rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/relation.json diff --git a/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/input.json b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/input.json new file mode 100644 index 00000000..b0fbc742 --- /dev/null +++ b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/input.json @@ -0,0 +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} \ No newline at end of file diff --git a/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/metadata.json b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/metadata.json new file mode 100644 index 00000000..b6fbfa52 --- /dev/null +++ b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/metadata.json @@ -0,0 +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"} \ No newline at end of file diff --git a/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/policy.rego b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/policy.rego new file mode 100644 index 00000000..45cc662b --- /dev/null +++ b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/policy.rego @@ -0,0 +1,21 @@ +package hws_ak_no_use_for_one_year_109 +import rego.v1 + +now_ns := time.now_ns() + +default risk := false + +risk if { + count(ak_no_use_for_one_year) > 0 +} + +user_name := input.UserAttribute.name +user_id := input.UserAttribute.domain_id + +ak_no_use_for_one_year contains p if { + some p in input.CredentialsDetail + p.status == "active" + last_used_date_ns := time.parse_rfc3339_ns(p.last_use_time) + tmp := time.add_date(last_used_date_ns, 0, 0, 365) + tmp < now_ns +} diff --git a/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/relation.json b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/relation.json new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/rules/HUAWEI_CLOUD/HUAWEI_CLOUD_IAM User_202511112036_1023138/relation.json @@ -0,0 +1 @@ +[] \ No newline at end of file