internal/resources/providers/awslib/iam/iam.go (130 lines of code) (raw):

// Licensed to Elasticsearch B.V. under one or more contributor // license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright // ownership. Elasticsearch B.V. licenses this file to you under // the Apache License, Version 2.0 (the "License"); you may // not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. package iam import ( "context" "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/accessanalyzer" iamsdk "github.com/aws/aws-sdk-go-v2/service/iam" "github.com/aws/aws-sdk-go-v2/service/iam/types" "github.com/elastic/cloudbeat/internal/infra/clog" "github.com/elastic/cloudbeat/internal/resources/providers/awslib" ) type AccessManagement interface { GetIAMRolePermissions(ctx context.Context, roleName string) ([]RolePolicyInfo, error) GetPasswordPolicy(ctx context.Context) (awslib.AwsResource, error) GetUsers(ctx context.Context) ([]awslib.AwsResource, error) GetPolicies(ctx context.Context) ([]awslib.AwsResource, error) ListServerCertificates(ctx context.Context) (awslib.AwsResource, error) GetAccessAnalyzers(ctx context.Context) (awslib.AwsResource, error) } type Client interface { ListUsers(ctx context.Context, params *iamsdk.ListUsersInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListUsersOutput, error) ListMFADevices(ctx context.Context, params *iamsdk.ListMFADevicesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListMFADevicesOutput, error) ListAccessKeys(ctx context.Context, params *iamsdk.ListAccessKeysInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListAccessKeysOutput, error) ListAttachedRolePolicies(ctx context.Context, params *iamsdk.ListAttachedRolePoliciesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListAttachedRolePoliciesOutput, error) ListVirtualMFADevices(ctx context.Context, params *iamsdk.ListVirtualMFADevicesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListVirtualMFADevicesOutput, error) ListAttachedUserPolicies(ctx context.Context, params *iamsdk.ListAttachedUserPoliciesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListAttachedUserPoliciesOutput, error) ListUserPolicies(ctx context.Context, params *iamsdk.ListUserPoliciesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListUserPoliciesOutput, error) GetAccessKeyLastUsed(ctx context.Context, params *iamsdk.GetAccessKeyLastUsedInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetAccessKeyLastUsedOutput, error) GetAccountPasswordPolicy(ctx context.Context, params *iamsdk.GetAccountPasswordPolicyInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetAccountPasswordPolicyOutput, error) GetRole(ctx context.Context, params *iamsdk.GetRoleInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetRoleOutput, error) ListRoles(ctx context.Context, params *iamsdk.ListRolesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListRolesOutput, error) GetRolePolicy(ctx context.Context, params *iamsdk.GetRolePolicyInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetRolePolicyOutput, error) GetCredentialReport(ctx context.Context, params *iamsdk.GetCredentialReportInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetCredentialReportOutput, error) GetUserPolicy(ctx context.Context, params *iamsdk.GetUserPolicyInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetUserPolicyOutput, error) GenerateCredentialReport(ctx context.Context, params *iamsdk.GenerateCredentialReportInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GenerateCredentialReportOutput, error) ListPolicies(ctx context.Context, params *iamsdk.ListPoliciesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListPoliciesOutput, error) GetPolicy(ctx context.Context, params *iamsdk.GetPolicyInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetPolicyOutput, error) GetPolicyVersion(ctx context.Context, params *iamsdk.GetPolicyVersionInput, optFns ...func(*iamsdk.Options)) (*iamsdk.GetPolicyVersionOutput, error) ListEntitiesForPolicy(ctx context.Context, params *iamsdk.ListEntitiesForPolicyInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListEntitiesForPolicyOutput, error) ListServerCertificates(ctx context.Context, params *iamsdk.ListServerCertificatesInput, optFns ...func(*iamsdk.Options)) (*iamsdk.ListServerCertificatesOutput, error) } type AccessAnalyzerClient interface { ListAnalyzers(ctx context.Context, params *accessanalyzer.ListAnalyzersInput, optFns ...func(*accessanalyzer.Options)) (*accessanalyzer.ListAnalyzersOutput, error) } type Provider struct { log *clog.Logger client Client accessAnalyzerClients map[string]AccessAnalyzerClient } type RolePolicyInfo struct { PolicyARN string iamsdk.GetRolePolicyOutput } // User Override SDK User type type User struct { AccessKeys []AccessKey `json:"access_keys,omitempty"` MFADevices []AuthDevice `json:"mfa_devices,omitempty"` InlinePolicies []PolicyDocument `json:"inline_policies"` AttachedPolicies []types.AttachedPolicy `json:"attached_policies"` Name string `json:"name,omitempty"` LastAccess string `json:"last_access,omitempty"` Arn string `json:"arn,omitempty"` PasswordLastChanged string `json:"password_last_changed,omitempty"` MfaActive bool `json:"mfa_active"` PasswordEnabled bool `json:"password_enabled"` UserId string `json:"user_id"` } type AuthDevice struct { IsVirtual bool `json:"is_virtual"` types.MFADevice } type AccessKey struct { Active bool `json:"active"` HasUsed bool `json:"has_used"` LastAccess string `json:"last_access,omitempty"` RotationDate string `json:"rotation_date,omitempty"` } type PasswordPolicy struct { ReusePreventionCount int `json:"reuse_prevention_count"` RequireLowercase bool `json:"require_lowercase"` RequireUppercase bool `json:"require_uppercase"` RequireNumbers bool `json:"require_numbers"` RequireSymbols bool `json:"require_symbols"` MaxAgeDays int `json:"max_age_days"` MinimumLength int `json:"minimum_length"` } // CredentialReport credential report CSV output type CredentialReport struct { User string `csv:"user"` Arn string `csv:"arn"` UserCreation string `csv:"user_creation_time"` // can't be parsed as a bool, the value for the AWS account root user is always not_supported PasswordEnabled string `csv:"password_enabled"` PasswordLastUsed string `csv:"password_last_used"` PasswordLastChanged string `csv:"password_last_changed"` PasswordNextRotation string `csv:"password_next_rotation"` MfaActive bool `csv:"mfa_active"` AccessKey1Active bool `csv:"access_key_1_active"` AccessKey1LastRotated string `csv:"access_key_1_last_rotated"` AccessKey1LastUsed string `csv:"access_key_1_last_used_date"` AccessKey2Active bool `csv:"access_key_2_active"` AccessKey2LastRotated string `csv:"access_key_2_last_rotated"` AccessKey2LastUsed string `csv:"access_key_2_last_used_date"` Cert1Active bool `csv:"cert_1_active"` Cert2Active bool `csv:"cert_2_active"` } type Policy struct { types.Policy Document map[string]any `json:"document,omitempty"` Roles []types.PolicyRole `json:"roles"` } type Role struct { types.Role } type ServerCertificatesInfo struct { Certificates []types.ServerCertificateMetadata `json:"certificates"` } type PolicyDocument struct { PolicyName string `json:"PolicyName,omitempty"` Policy string `json:"policy,omitempty"` } func NewIAMProvider(ctx context.Context, log *clog.Logger, cfg aws.Config, crossRegionFactory awslib.CrossRegionFactory[AccessAnalyzerClient]) *Provider { provider := Provider{ log: log, client: iamsdk.NewFromConfig(cfg), } if crossRegionFactory != nil { m := crossRegionFactory.NewMultiRegionClients(ctx, awslib.AllRegionSelector(), cfg, func(cfg aws.Config) AccessAnalyzerClient { return accessanalyzer.NewFromConfig(cfg) }, log) provider.accessAnalyzerClients = m.GetMultiRegionsClientMap() } return &provider }