From c0a489807449f22dbce7cb0b4da9c6f247d44aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Sun, 10 Aug 2025 22:48:23 -0700 Subject: [PATCH 01/30] chore(changelog): update (#8496) --- prowler/CHANGELOG.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 4e71d3f6cf..133b5163ca 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -2,7 +2,24 @@ All notable changes to the **Prowler SDK** are documented in this file. -## [v5.10.1] (Prowler UNRELEASED) + +## [v5.11.0] (Prowler UNRELEASED) + +### Added + +### Changed + +### Fixed + +--- + +## [v5.10.2] (Prowler UNRELEASED) + +### Fixed + +--- + +## [v5.10.1] (Prowler v5.10.1) ### Fixed - Remove invalid requirements from CIS 1.0 for GitHub provider [(#8472)](https://github.com/prowler-cloud/prowler/pull/8472) From 760723874c25eedbedffec6d5700c35eb153f399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Mart=C3=ADn?= Date: Sun, 10 Aug 2025 23:20:10 -0700 Subject: [PATCH 02/30] fix(prowler-threatscore): order the requirements by id (#8495) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + .../aws/prowler_threatscore_aws.json | 1140 ++++++++--------- 2 files changed, 571 insertions(+), 570 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 133b5163ca..cf2e158655 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ## [v5.10.2] (Prowler UNRELEASED) ### Fixed +- Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495) --- diff --git a/prowler/compliance/aws/prowler_threatscore_aws.json b/prowler/compliance/aws/prowler_threatscore_aws.json index 8ef5d24b93..4763f40ddd 100644 --- a/prowler/compliance/aws/prowler_threatscore_aws.json +++ b/prowler/compliance/aws/prowler_threatscore_aws.json @@ -275,25 +275,6 @@ } ] }, - { - "Id": "1.3.1", - "Description": "Ensure IAM policies that allow full *:* administrative privileges are not attached", - "Checks": [ - "iam_aws_attached_policy_no_administrative_privileges", - "iam_customer_attached_policy_no_administrative_privileges" - ], - "Attributes": [ - { - "Title": "IAM policies with full privileges not attached", - "Section": "1. IAM", - "SubSection": "1.3 Privilege Escalation Prevention", - "AttributeDescription": "IAM policies define permissions for users, groups, and roles, controlling access to AWS resources. Following the principle of least privilege, users should be granted only the permissions necessary to perform their tasks. Instead of assigning broad administrative privileges, permissions should be carefully crafted to allow only the required actions.", - "AdditionalInformation": "Starting with minimal permissions and granting additional access as needed is significantly more secure than providing excessive permissions and attempting to restrict them later. Assigning full administrative privileges increases the risk of unauthorized or accidental actions that could compromise AWS resources. IAM policies containing Effect: Allow, Action: , Resource: should be removed to prevent unrestricted access and enforce security best practices.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, { "Id": "1.2.3", "Description": "Ensure a support role has been created to manage incidents with AWS Support", @@ -330,24 +311,6 @@ } ] }, - { - "Id": "4.1.3", - "Description": "Ensure that all expired SSL/TLS certificates stored in AWS IAM are removed", - "Checks": [ - "iam_no_expired_server_certificates_stored" - ], - "Attributes": [ - { - "Title": "Expired SSL/TLS certificates removed", - "Section": "4. Encryption", - "SubSection": "4.1 In-Transit", - "AttributeDescription": "To enable HTTPS connections for applications and websites hosted on AWS, an SSL/TLS server certificate is required. AWS provides two options for managing certificates: AWS Certificate Manager (ACM) – The preferred method for managing SSL/TLS certificates, automating renewals and deployment. IAM Certificate Storage – Used only when deploying SSL/TLS certificates in regions not supported by ACM. IAM securely encrypts private keys and stores them, but certificates must be obtained from an external provider. ACM certificates cannot be uploaded to IAM, and IAM certificates cannot be managed from the IAM Console.", - "AdditionalInformation": "Removing expired SSL/TLS certificates prevents the accidental deployment of invalid certificates, which could cause service disruptions, security warnings, and loss of credibility for applications using AWS services like Elastic Load Balancer (ELB). As a best practice, expired certificates should be deleted to maintain a secure and trusted application environment.", - "LevelOfRisk": 5, - "Weight": 1000 - } - ] - }, { "Id": "1.2.5", "Description": "Avoid the use of the 'root' account", @@ -402,6 +365,25 @@ } ] }, + { + "Id": "1.3.1", + "Description": "Ensure IAM policies that allow full *:* administrative privileges are not attached", + "Checks": [ + "iam_aws_attached_policy_no_administrative_privileges", + "iam_customer_attached_policy_no_administrative_privileges" + ], + "Attributes": [ + { + "Title": "IAM policies with full privileges not attached", + "Section": "1. IAM", + "SubSection": "1.3 Privilege Escalation Prevention", + "AttributeDescription": "IAM policies define permissions for users, groups, and roles, controlling access to AWS resources. Following the principle of least privilege, users should be granted only the permissions necessary to perform their tasks. Instead of assigning broad administrative privileges, permissions should be carefully crafted to allow only the required actions.", + "AdditionalInformation": "Starting with minimal permissions and granting additional access as needed is significantly more secure than providing excessive permissions and attempting to restrict them later. Assigning full administrative privileges increases the risk of unauthorized or accidental actions that could compromise AWS resources. IAM policies containing Effect: Allow, Action: , Resource: should be removed to prevent unrestricted access and enforce security best practices.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, { "Id": "1.3.2", "Description": "Ensure access to AWSCloudShellFullAccess is restricted", @@ -438,78 +420,6 @@ } ] }, - { - "Id": "4.1.1", - "Description": "Ensure S3 Bucket Policy is set to deny HTTP requests", - "Checks": [ - "s3_bucket_secure_transport_policy" - ], - "Attributes": [ - { - "Title": "S3 bucket deny HTTP requests", - "Section": "4. Encryption", - "SubSection": "4.1 In-Transit", - "AttributeDescription": "Amazon S3 bucket permissions can be configured using a bucket policy to enforce access restrictions. To enhance security, objects within the bucket should be made accessible only via HTTPS, ensuring encrypted data transmission.", - "AdditionalInformation": "By default, Amazon S3 accepts both HTTP and HTTPS requests, which can expose data to interception. To enforce secure access, HTTP requests should be explicitly denied in the bucket policy. Simply allowing HTTPS without blocking HTTP does not fully comply with security best practices, as unencrypted requests may still be accepted.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "4.1.2", - "Description": "Ensure that EC2 Metadata Service only allows IMDSv2", - "Checks": [ - "ec2_instance_imdsv2_enabled" - ], - "Attributes": [ - { - "Title": "EC2 Metadata Service only allows IMDSv2", - "Section": "4. Encryption", - "SubSection": "4.1 In-Transit", - "AttributeDescription": "AWS EC2 instances allow users to choose between Instance Metadata Service Version 1 (IMDSv1), which uses a request/response model, or Instance Metadata Service Version 2 (IMDSv2), which uses a session-based approach for enhanced security", - "AdditionalInformation": "Instance metadata refers to the data about an EC2 instance, such as host names, events, and security groups, that is used for managing and configuring the instance. When enabling the Metadata Service, users can opt for either IMDSv1, which operates via a simple request/response model, or IMDSv2, which implements session authentication for additional security. With IMDSv2, each request is secured by session-based authentication, ensuring that all interactions with the instance's metadata and credentials are protected. IMDSv1, on the other hand, may expose instances to Server-Side Request Forgery (SSRF) attacks. To improve security, Amazon recommends using IMDSv2", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.2.1", - "Description": "Ensure MFA Delete is enabled on S3 buckets", - "Checks": [ - "s3_bucket_no_mfa_delete" - ], - "Attributes": [ - { - "Title": "MFA delete enabled on S3 buckets", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Enabling MFA Delete on a sensitive or classified Amazon S3 bucket adds an extra layer of protection by requiring two-factor authentication for critical actions, such as deleting object versions or changing the bucket’s versioning state.", - "AdditionalInformation": "MFA Delete helps prevent accidental or malicious deletions by requiring an additional authentication step. This mitigates the risk of data loss due to compromised credentials or unauthorized access, ensuring that critical objects remain protected.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "2.2.2", - "Description": "Ensure all data in Amazon S3 has been discovered, classified, and secured when necessary", - "Checks": [ - "macie_is_enabled" - ], - "Attributes": [ - { - "Title": "Macie enabled", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon S3 buckets may store sensitive data that needs to be discovered, classified, monitored, and protected to maintain security and compliance. Amazon Macie, along with third-party tools, can automatically inventory S3 buckets and identify sensitive data at scale.", - "AdditionalInformation": "Using automated data discovery and classification tools, such as Amazon Macie, enhances security by continuously monitoring S3 buckets for sensitive information. Macie leverages machine learning and pattern matching to detect and protect critical data, reducing the risk of data leaks and unauthorized access.", - "LevelOfRisk": 1, - "Weight": 1 - } - ] - }, { "Id": "2.1.1", "Description": "Ensure the default security group of every VPC restricts all traffic", @@ -586,6 +496,180 @@ } ] }, + { + "Id": "2.1.5", + "Description": "Ensure ApiGateway endpoint is not public", + "Checks": [ + "apigateway_restapi_public" + ], + "Attributes": [ + { + "Title": "ApiGateway endpoint is public", + "Section": "2. Attack Surface", + "SubSection": "2.1 Network", + "AttributeDescription": "AWS API Gateway allows developers to create, deploy, and manage APIs that connect applications to backend services. By default, API Gateway endpoints can be publicly accessible, meaning they can be invoked from anywhere on the internet. To enhance security, API Gateway endpoints should be restricted to private networks using VPC links, private API settings, or access control mechanisms to ensure that only authorized entities can interact with the API.", + "AdditionalInformation": "Publicly accessible API Gateway endpoints can expose backend services to unauthorized access, data leaks, and potential exploitation. Attackers may attempt brute-force authentication, injection attacks, or abuse API functionality if access is not properly restricted. To reduce the attack surface, API Gateway endpoints should be limited to internal use or protected with authentication, IAM permissions, WAF rules, or private VPC access to ensure only trusted users and systems can invoke the API.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.1.6", + "Description": "Ensure that ec2 common ports from instances are not internet-exposed", + "Checks": [ + "ec2_instance_port_cassandra_exposed_to_internet", + "ec2_instance_port_cifs_exposed_to_internet", + "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", + "ec2_instance_port_ftp_exposed_to_internet", + "ec2_instance_port_kafka_exposed_to_internet", + "ec2_instance_port_kerberos_exposed_to_internet", + "ec2_instance_port_ldap_exposed_to_internet", + "ec2_instance_port_memcached_exposed_to_internet", + "ec2_instance_port_mongodb_exposed_to_internet", + "ec2_instance_port_mysql_exposed_to_internet", + "ec2_instance_port_oracle_exposed_to_internet", + "ec2_instance_port_postgresql_exposed_to_internet", + "ec2_instance_port_rdp_exposed_to_internet", + "ec2_instance_port_redis_exposed_to_internet", + "ec2_instance_port_sqlserver_exposed_to_internet", + "ec2_instance_port_ssh_exposed_to_internet", + "ec2_instance_port_telnet_exposed_to_internet" + ], + "Attributes": [ + { + "Title": "Common ports from instances are not exposed", + "Section": "2. Attack Surface", + "SubSection": "2.1 Network", + "AttributeDescription": "Amazon EC2 instances can run various services that communicate over common ports such as 22 (SSH), 3389 (RDP), 80 (HTTP), and 443 (HTTPS) (and more). If these ports are open to the internet, attackers can attempt unauthorized access, brute-force attacks, or exploit known vulnerabilities. To reduce security risks, EC2 instances should be configured so that common ports are not exposed to the public internet, unless explicitly required and properly secured.", + "AdditionalInformation": "Exposing common ports directly to the internet increases the attack surface and risks unauthorized access or system compromise. Attackers frequently scan for open ports to target misconfigured or unpatched services. To enhance security, access to EC2 common ports should be restricted using security groups, network ACLs, and VPC configurations, ensuring that only trusted networks and users can connect.", + "LevelOfRisk": 5, + "Weight": 1000 + } + ] + }, + { + "Id": "2.1.7", + "Description": "Ensure that ec2 security groups do not allow ingress from internet to common ports", + "Checks": [ + "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", + "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23" + ], + "Attributes": [ + { + "Title": "Common ports from security groups do not allow ingress traffic", + "Section": "2. Attack Surface", + "SubSection": "2.1 Network", + "AttributeDescription": "Amazon EC2 security groups act as virtual firewalls, controlling inbound and outbound traffic to instances. If a security group allows ingress (incoming traffic) from the internet (0.0.0.0/0 or ::/0) to common ports such as 22 (SSH), 3389 (RDP), 80 (HTTP), or 443 (HTTPS) (and more), it creates a significant security risk. To minimize exposure, security groups should be configured to restrict ingress access to these ports to only trusted IP addresses or internal networks.", + "AdditionalInformation": "Allowing unrestricted inbound traffic to common ports increases the risk of brute-force attacks, unauthorized access, and exploitation of vulnerabilities. Attackers actively scan for open ports on public-facing EC2 instances to gain unauthorized control. To reduce security risks, ingress rules should be restricted using least privilege principles, IP whitelisting, VPN access, or bastion hosts, ensuring that only authorized users and networks can connect.", + "LevelOfRisk": 5, + "Weight": 1000 + } + ] + }, + { + "Id": "2.1.8", + "Description": "Ensure EKS cluster Network Policy is Enabled and Set as Appropriate", + "Checks": [ + "eks_cluster_network_policy_enabled" + ], + "Attributes": [ + { + "Title": "EKS cluster Network Policy is Enabled and Set as Appropriate", + "Section": "2. Attack Surface", + "SubSection": "2.1 Network", + "AttributeDescription": "A Network Policy defines how network traffic is controlled and restricted between workloads within a cloud environment. Enforcing network policies ensures that only authorized communication occurs between services, reducing the risk of unauthorized access and lateral movement. It is recommended to enable Network Policies and configure them appropriately to enforce least privilege access and secure communication between workloads.", + "AdditionalInformation": "Without properly configured Network Policies, workloads may be exposed to unnecessary or unauthorized network traffic, increasing the risk of data leaks, exploitation, or lateral movement by attackers. By enabling and enforcing Network Policies, organizations can limit communication between workloads, ensuring that only approved and necessary network interactions are allowed, minimizing the attack surface and enhancing overall security.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.1.9", + "Description": "Ensure EKS Clusters are not publicly accessible", + "Checks": [ + "eks_cluster_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "EKS Clusters are not publicly accessible", + "Section": "2. Attack Surface", + "SubSection": "2.1 Network", + "AttributeDescription": "Amazon Elastic Kubernetes Service (EKS) clusters manage containerized applications and can be configured with either private or public access. If an EKS cluster is publicly accessible, it means that the Kubernetes API endpoint can be reached from the internet, increasing the risk of unauthorized access and attacks. To enhance security, EKS clusters should be restricted to private networks and accessed only through secure VPNs, VPC peering, or AWS PrivateLink.", + "AdditionalInformation": "Exposing an EKS cluster to the public internet increases the risk of brute-force attacks, credential theft, and unauthorized access to Kubernetes workloads. Attackers could exploit misconfigured RBAC policies or API vulnerabilities to gain control over the cluster. To reduce security risks, EKS clusters should be configured with private endpoints, ensuring that only trusted networks and IAM-authenticated users can manage Kubernetes resources.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.1.10", + "Description": "Ensure EKS Clusters are created with Private Nodes", + "Checks": [ + "eks_cluster_private_nodes_enabled" + ], + "Attributes": [ + { + "Title": "EKS Clusters are created with Private Nodes", + "Section": "2. Attack Surface", + "SubSection": "2.1 Network", + "AttributeDescription": "Amazon Elastic Kubernetes Service (EKS) clusters run workloads on worker nodes, which can be either public or private. If EKS clusters are created with public nodes, these nodes are assigned public IP addresses, making them accessible from the internet, which increases the risk of unauthorized access and potential attacks. To enhance security, EKS clusters should be created with private nodes that operate within private subnets and are only accessible through secured networking configurations such as VPNs, VPC peering, or AWS PrivateLink.", + "AdditionalInformation": "Using public nodes in EKS exposes Kubernetes workloads to the internet, increasing the risk of unauthorized access, lateral movement, and potential exploitation. Attackers can target misconfigured workloads, open services, or unsecured API endpoints. By creating EKS clusters with private nodes, organizations can restrict access, limit exposure to public threats, and enforce network segmentation, ensuring that workloads remain secure and isolated within a private VPC environment.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.2.1", + "Description": "Ensure MFA Delete is enabled on S3 buckets", + "Checks": [ + "s3_bucket_no_mfa_delete" + ], + "Attributes": [ + { + "Title": "MFA delete enabled on S3 buckets", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Enabling MFA Delete on a sensitive or classified Amazon S3 bucket adds an extra layer of protection by requiring two-factor authentication for critical actions, such as deleting object versions or changing the bucket’s versioning state.", + "AdditionalInformation": "MFA Delete helps prevent accidental or malicious deletions by requiring an additional authentication step. This mitigates the risk of data loss due to compromised credentials or unauthorized access, ensuring that critical objects remain protected.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "2.2.2", + "Description": "Ensure all data in Amazon S3 has been discovered, classified, and secured when necessary", + "Checks": [ + "macie_is_enabled" + ], + "Attributes": [ + { + "Title": "Macie enabled", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon S3 buckets may store sensitive data that needs to be discovered, classified, monitored, and protected to maintain security and compliance. Amazon Macie, along with third-party tools, can automatically inventory S3 buckets and identify sensitive data at scale.", + "AdditionalInformation": "Using automated data discovery and classification tools, such as Amazon Macie, enhances security by continuously monitoring S3 buckets for sensitive information. Macie leverages machine learning and pattern matching to detect and protect critical data, reducing the risk of data leaks and unauthorized access.", + "LevelOfRisk": 1, + "Weight": 1 + } + ] + }, { "Id": "2.2.3", "Description": "Ensure EBS snapshots are not publicly accessible", @@ -604,60 +688,6 @@ } ] }, - { - "Id": "4.2.1", - "Description": "Ensure EBS volume encryption is enabled in all regions", - "Checks": [ - "ec2_ebs_volume_encryption" - ], - "Attributes": [ - { - "Title": "EBS volume encryption", - "Section": "4. Encryption", - "SubSection": "4.2 At-Rest", - "AttributeDescription": "Amazon Elastic Compute Cloud (EC2) supports encryption at rest for Elastic Block Store (EBS) volumes, ensuring that stored data remains protected. While EBS encryption is disabled by default, organizations can enforce automatic encryption of newly created volumes to enhance data security and compliance.", - "AdditionalInformation": "Enforcing EBS volume encryption reduces the risk of data exposure, unauthorized access, and compliance violations. If encryption remains intact, even if storage is compromised, data remains unreadable to unauthorized users. Encrypting data at rest ensures that sensitive information is protected against accidental disclosure, insider threats, and external attacks.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "4.2.2", - "Description": "Ensure that encryption-at-rest is enabled for RDS instances", - "Checks": [ - "rds_instance_storage_encrypted" - ], - "Attributes": [ - { - "Title": "RDS instances encryption at rest enabled", - "Section": "4. Encryption", - "SubSection": "4.2 At-Rest", - "AttributeDescription": "Amazon Relational Database Service (RDS) supports encryption at rest using the industry-standard AES-256 encryption algorithm to secure database instances and their associated storage. Once enabled, RDS encryption automatically handles access authentication and decryption, ensuring secure data storage with minimal performance impact.", - "AdditionalInformation": "Databases often contain sensitive and business-critical information, making encryption essential to protect against unauthorized access and data breaches. Enabling RDS encryption ensures that underlying storage, automated backups, read replicas, and snapshots are all encrypted, preventing accidental or malicious data exposure while maintaining compliance with security best practices.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "2.3.1", - "Description": "Ensure SNS topics do not allow global send or subscribe", - "Checks": [ - "sns_topics_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "SNS topics do not allow global send or subscribe", - "Section": "2. Attack Surface", - "SubSection": "2.3 Application", - "AttributeDescription": "Amazon Simple Notification Service (SNS) topics enable messaging between AWS services, applications, and users. By default, SNS topics should be restricted to trusted AWS accounts or IAM roles to prevent unauthorized access. Allowing global send (sns:Publish) or subscribe (sns:Subscribe) permissions means any AWS account or unauthenticated entity could send messages or subscribe to the topic, potentially leading to spam, data leaks, or misuse of notifications.", - "AdditionalInformation": "SNS topics with global send or subscribe permissions expose AWS environments to unauthorized message injection, data exfiltration, and Denial-of-Service (DoS) attacks. An attacker could flood an SNS topic with malicious or fraudulent messages, leading to unexpected charges or service disruptions. Restricting access ensures that only authorized AWS accounts, applications, or IAM roles can send and receive messages, reducing security risks and protecting system integrity.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, { "Id": "2.2.4", "Description": "Ensure RDS snapshots are not publicly accessible", @@ -713,18 +743,234 @@ ] }, { - "Id": "2.1.5", - "Description": "Ensure ApiGateway endpoint is not public", + "Id": "2.2.7", + "Description": "Ensure DocumentDB manual cluster snapshot is not public", "Checks": [ - "apigateway_restapi_public" + "documentdb_cluster_public_snapshot" ], "Attributes": [ { - "Title": "ApiGateway endpoint is public", + "Title": "DocumentDB manual cluster snapshot is not public", "Section": "2. Attack Surface", - "SubSection": "2.1 Network", - "AttributeDescription": "AWS API Gateway allows developers to create, deploy, and manage APIs that connect applications to backend services. By default, API Gateway endpoints can be publicly accessible, meaning they can be invoked from anywhere on the internet. To enhance security, API Gateway endpoints should be restricted to private networks using VPC links, private API settings, or access control mechanisms to ensure that only authorized entities can interact with the API.", - "AdditionalInformation": "Publicly accessible API Gateway endpoints can expose backend services to unauthorized access, data leaks, and potential exploitation. Attackers may attempt brute-force authentication, injection attacks, or abuse API functionality if access is not properly restricted. To reduce the attack surface, API Gateway endpoints should be limited to internal use or protected with authentication, IAM permissions, WAF rules, or private VPC access to ensure only trusted users and systems can invoke the API.", + "SubSection": "2.2 Storage", + "AttributeDescription": "AWS DocumentDB manual cluster snapshots store backups of DocumentDB clusters, containing sensitive database information such as application data, configurations, and credentials. By default, snapshots are private, but they can be manually shared or made public, which poses a significant security risk. To prevent unauthorized access, DocumentDB manual cluster snapshots should never be publicly accessible unless explicitly required and properly secured.", + "AdditionalInformation": "Publicly accessible DocumentDB snapshots expose critical database information, increasing the risk of data breaches, unauthorized access, and compliance violations. Attackers could restore the snapshot in their own AWS account and gain full access to the database content. To protect sensitive data, DocumentDB snapshots should only be shared with specific AWS accounts or remain private, following least privilege principles and AWS security best practices.", + "LevelOfRisk": 5, + "Weight": 1000 + } + ] + }, + { + "Id": "2.2.8", + "Description": "Ensure that public access to EBS snapshots is disabled", + "Checks": [ + "ec2_ebs_snapshot_account_block_public_access" + ], + "Attributes": [ + { + "Title": "Public access to EBS snapshots is disabled", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon Elastic Block Store (EBS) snapshots are backups of EC2 volumes that may contain sensitive data, such as credentials, application configurations, and customer records. By default, EBS snapshots are private, but they can be manually shared or made public, allowing anyone to copy or restore them. To prevent unauthorized access and data exposure, public access to EBS snapshots should always be disabled.", + "AdditionalInformation": "Publicly accessible EBS snapshots pose a significant security risk, as attackers can restore and extract sensitive data if a snapshot is exposed. Misconfigured public snapshots have led to data breaches and compliance violations in the past. To mitigate this risk, EBS snapshots should be kept private or explicitly shared only with trusted AWS accounts, following least privilege principles to protect critical data and maintain security compliance.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.2.9", + "Description": "Ensure EFS mount targets are not publicly accessible", + "Checks": [ + "efs_mount_target_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "No EFS mount targets are publicly accessible", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon Elastic File System (EFS) provides scalable, shared file storage for AWS services. EFS mount targets allow instances to connect to the file system within a VPC. By default, EFS mount targets can be configured with public accessibility, making them reachable from the internet. To enhance security, EFS mount targets should be restricted to private networks and should not be publicly accessible unless explicitly required and properly secured.", + "AdditionalInformation": "Publicly accessible EFS mount targets expose stored data to unauthorized access, cyberattacks, and data breaches. Attackers could exploit misconfigured security groups or network ACLs to access or modify files. To reduce security risks, EFS mount targets should be restricted to private subnets, with access limited to trusted VPCs, security groups, and IAM roles, ensuring secure file storage and controlled access.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "2.2.10", + "Description": "Ensure that EFS do not have policies which allow access to any client within the VPC", + "Checks": [ + "efs_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "No EFS have policies which allow access to any client within the VPC", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon Elastic File System (EFS) provides shared storage that can be accessed by multiple EC2 instances and services within a VPC. EFS access is controlled through resource-based policies that define which clients can connect. If an EFS policy allows access to any client within the VPC, it increases the risk of unauthorized access and data exposure. To enhance security, EFS policies should be restricted to specific IAM roles, security groups, or trusted resources instead of granting broad access to all VPC clients.", + "AdditionalInformation": "Allowing any client within a VPC to access an EFS file system increases the risk of data leaks, accidental modifications, or unauthorized access by compromised instances or misconfigured services. To minimize exposure, EFS policies should enforce least privilege access, restricting permissions to specific instances, roles, or users that require access, ensuring secure file storage and controlled data access.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "2.2.11", + "Description": "Ensure Elasticache Cluster is not using a public subnet", + "Checks": [ + "elasticache_cluster_uses_public_subnet" + ], + "Attributes": [ + { + "Title": "Elasticache Cluster is not using a public subnet", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon ElastiCache provides in-memory caching services using Redis and Memcached. By default, ElastiCache clusters can be deployed in either public or private subnets. If an ElastiCache cluster is placed in a public subnet, it becomes accessible from the internet, which significantly increases the risk of unauthorized access and data breaches. To enhance security, ElastiCache clusters should only be deployed in private subnets, ensuring restricted access within a VPC.", + "AdditionalInformation": "Deploying an ElastiCache cluster in a public subnet exposes it to external threats, such as unauthorized access, brute-force attacks, and potential data exfiltration. Attackers could exploit misconfigurations to access cached data or disrupt services. By restricting ElastiCache clusters to private subnets, organizations can limit access to trusted resources, enforce VPC security controls, and reduce the attack surface, ensuring secure and efficient caching operations.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "2.2.12", + "Description": "Ensure S3 Glacier vaults have not policies which allow access to everyone", + "Checks": [ + "glacier_vaults_policy_public_access" + ], + "Attributes": [ + { + "Title": "S3 Glacier vaults have not policies which allow access to everyone", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon S3 Glacier provides low-cost, long-term storage for archival data. Glacier vaults can be configured with resource-based policies that control access. If a Glacier vault policy allows access to everyone, unauthorized users could retrieve or delete archived data, leading to data exposure or loss. To enhance security, Glacier vault policies should be restricted to specific AWS accounts, IAM roles, or trusted entities, ensuring only authorized users can access or manage archived data.", + "AdditionalInformation": "Allowing public access to S3 Glacier vaults poses a significant security risk, increasing the chance of data breaches, unauthorized deletions, or compliance violations. Attackers could restore and download sensitive archived data if the vault is misconfigured. To prevent unauthorized access, Glacier vaults should have strict access controls, using IAM policies, encryption, and resource-based permissions, ensuring that only trusted users and systems can interact with archived data.", + "LevelOfRisk": 5, + "Weight": 1000 + } + ] + }, + { + "Id": "2.2.13", + "Description": "Ensure Glue Data Catalogs are not publicly accessible", + "Checks": [ + "glue_data_catalogs_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "Glue Data Catalogs are not publicly accessible", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "AWS Glue Data Catalog is a centralized metadata repository used to store and manage schema information for data lakes and analytics workflows. By default, Glue Data Catalogs can be configured to allow public access, which poses a significant security risk if sensitive metadata is exposed. To enhance security, Glue Data Catalogs should be restricted to specific AWS accounts, IAM roles, or trusted services, ensuring that only authorized users can access or modify catalog information.", + "AdditionalInformation": "Allowing public access to Glue Data Catalogs increases the risk of unauthorized access, data leaks, and compliance violations. Attackers could gain insights into an organization’s data structure or modify catalog entries, leading to potential data corruption or unauthorized data exposure. To reduce security risks, Glue Data Catalogs should be secured using IAM policies, resource-based permissions, and AWS Lake Formation, ensuring that only trusted accounts and services can interact with metadata.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.2.14", + "Description": "Ensure there are no internet exposed KMS keys", + "Checks": [ + "kms_key_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "No internet exposed KMS keys", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "AWS Key Management Service (KMS) provides secure encryption key management for data encryption and cryptographic operations. If KMS keys are exposed to the internet, unauthorized entities could potentially use, modify, or compromise encryption keys, leading to data breaches and security vulnerabilities. To enhance security, KMS keys should be restricted to trusted AWS accounts, IAM roles, and specific AWS services, ensuring that only authorized users and systems can access and manage them.", + "AdditionalInformation": "Exposing KMS keys to the public poses a critical security risk, as compromised keys can lead to unauthorized data decryption, loss of data integrity, and compliance violations. Attackers could potentially use public KMS keys to encrypt or decrypt sensitive data, undermining security controls. To prevent unauthorized access, KMS key policies should enforce strict access control using IAM permissions, VPC endpoint policies, and AWS PrivateLink, ensuring that encryption operations remain fully secured and isolated from the public internet.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "2.2.15", + "Description": "Ensure that S3 buckets have not policies which allow WRITE access", + "Checks": [ + "s3_bucket_policy_public_write_access" + ], + "Attributes": [ + { + "Title": "S3 buckets have not policies which allow WRITE access", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon S3 buckets store and manage data, files, and application assets. Bucket policies control access permissions, and if an S3 bucket has a policy that allows WRITE access to everyone, unauthorized users can upload, modify, or delete objects, leading to data tampering, security breaches, or service disruptions. To enhance security, S3 bucket policies should be restricted to specific AWS accounts, IAM roles, or trusted services, ensuring only authorized users have WRITE permissions.", + "AdditionalInformation": "Allowing unrestricted WRITE access to an S3 bucket increases the risk of unauthorized modifications, data injection attacks, and accidental data loss. Attackers could upload malicious files, delete critical data, or overwrite important configurations. To prevent unauthorized changes, S3 bucket policies should explicitly deny public WRITE access, enforce least privilege access control, and use AWS Block Public Access settings to ensure secure and controlled data storage.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.2.16", + "Description": "Ensure there are no S3 buckets listable by Everyone or Any AWS customer", + "Checks": [ + "s3_bucket_public_list_acl" + ], + "Attributes": [ + { + "Title": "No S3 buckets are listable by Everyone or Any AWS customer", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon S3 buckets store sensitive data and should have restricted access permissions. If an S3 bucket is listable by Everyone or Any AWS customer, unauthorized users can enumerate the objects within the bucket, potentially exposing sensitive information such as filenames, metadata, or even public datasets. To enhance security, S3 bucket permissions should be configured to restrict LIST access to only authorized IAM roles, AWS accounts, or specific services.", + "AdditionalInformation": "Allowing public or AWS-wide LIST access increases the risk of data enumeration, unauthorized access, and information leaks. Attackers or unauthorized users could identify and analyze stored files, extract metadata, or infer sensitive data. To mitigate this risk, S3 bucket policies should explicitly deny public LIST access, enforce least privilege permissions, and use AWS Block Public Access settings to prevent unintended data exposure.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.2.17", + "Description": "Ensure there are no S3 buckets writable by Everyone or Any AWS customer", + "Checks": [ + "s3_bucket_public_write_acl" + ], + "Attributes": [ + { + "Title": "No S3 buckets writable by Everyone or Any AWS customer", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "Amazon S3 buckets should have strict access controls to prevent unauthorized modifications. If an S3 bucket is writable by Everyone or Any AWS customer, it allows unauthorized users to upload, modify, or delete objects, leading to data corruption, security breaches, and compliance risks. To enhance security, S3 bucket permissions should be restricted to trusted IAM roles, AWS accounts, or specific services.", + "AdditionalInformation": "Allowing public or AWS-wide WRITE access creates a significant security risk, as attackers can inject malicious files, overwrite critical data, or delete essential objects. This could lead to data loss, malware distribution, or unauthorized system modifications. To prevent unauthorized changes, S3 bucket policies should explicitly deny public WRITE access, enforce least privilege access, and use AWS Block Public Access settings to secure data integrity and prevent unauthorized modifications.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.2.18", + "Description": "Ensure Secrets Manager secrets are not publicly accessible", + "Checks": [ + "secretsmanager_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "Secrets Manager secrets are not publicly accessible", + "Section": "2. Attack Surface", + "SubSection": "2.2 Storage", + "AttributeDescription": "AWS Secrets Manager is used to securely store and manage sensitive information, such as API keys, database credentials, and encryption keys. By default, Secrets Manager secrets should be restricted to authorized IAM roles and AWS services. If a secret is publicly accessible, it can be exposed to unauthorized users, leading to data leaks, security breaches, and potential exploitation of sensitive credentials. To enhance security, Secrets Manager secrets should be strictly controlled using IAM policies and resource-based permissions.", + "AdditionalInformation": "Allowing public access to Secrets Manager secrets creates a critical security vulnerability, as attackers could retrieve, misuse, or exfiltrate sensitive information. Compromised secrets could lead to unauthorized access to databases, applications, or cloud services, resulting in data breaches, financial loss, or compliance violations. To mitigate this risk, Secrets Manager secrets should be restricted using least privilege IAM permissions, encrypted with AWS KMS, and accessed only by trusted AWS services and roles, ensuring secure and controlled secret management.", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "2.3.1", + "Description": "Ensure SNS topics do not allow global send or subscribe", + "Checks": [ + "sns_topics_not_publicly_accessible" + ], + "Attributes": [ + { + "Title": "SNS topics do not allow global send or subscribe", + "Section": "2. Attack Surface", + "SubSection": "2.3 Application", + "AttributeDescription": "Amazon Simple Notification Service (SNS) topics enable messaging between AWS services, applications, and users. By default, SNS topics should be restricted to trusted AWS accounts or IAM roles to prevent unauthorized access. Allowing global send (sns:Publish) or subscribe (sns:Subscribe) permissions means any AWS account or unauthenticated entity could send messages or subscribe to the topic, potentially leading to spam, data leaks, or misuse of notifications.", + "AdditionalInformation": "SNS topics with global send or subscribe permissions expose AWS environments to unauthorized message injection, data exfiltration, and Denial-of-Service (DoS) attacks. An attacker could flood an SNS topic with malicious or fraudulent messages, leading to unexpected charges or service disruptions. Restricting access ensures that only authorized AWS accounts, applications, or IAM roles can send and receive messages, reducing security risks and protecting system integrity.", "LevelOfRisk": 4, "Weight": 100 } @@ -802,24 +1048,6 @@ } ] }, - { - "Id": "2.2.7", - "Description": "Ensure DocumentDB manual cluster snapshot is not public", - "Checks": [ - "documentdb_cluster_public_snapshot" - ], - "Attributes": [ - { - "Title": "DocumentDB manual cluster snapshot is not public", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "AWS DocumentDB manual cluster snapshots store backups of DocumentDB clusters, containing sensitive database information such as application data, configurations, and credentials. By default, snapshots are private, but they can be manually shared or made public, which poses a significant security risk. To prevent unauthorized access, DocumentDB manual cluster snapshots should never be publicly accessible unless explicitly required and properly secured.", - "AdditionalInformation": "Publicly accessible DocumentDB snapshots expose critical database information, increasing the risk of data breaches, unauthorized access, and compliance violations. Attackers could restore the snapshot in their own AWS account and gain full access to the database content. To protect sensitive data, DocumentDB snapshots should only be shared with specific AWS accounts or remain private, following least privilege principles and AWS security best practices.", - "LevelOfRisk": 5, - "Weight": 1000 - } - ] - }, { "Id": "2.3.6", "Description": "Ensure there are no EC2 AMIs set as Public", @@ -838,90 +1066,6 @@ } ] }, - { - "Id": "2.2.8", - "Description": "Ensure that public access to EBS snapshots is disabled", - "Checks": [ - "ec2_ebs_snapshot_account_block_public_access" - ], - "Attributes": [ - { - "Title": "Public access to EBS snapshots is disabled", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon Elastic Block Store (EBS) snapshots are backups of EC2 volumes that may contain sensitive data, such as credentials, application configurations, and customer records. By default, EBS snapshots are private, but they can be manually shared or made public, allowing anyone to copy or restore them. To prevent unauthorized access and data exposure, public access to EBS snapshots should always be disabled.", - "AdditionalInformation": "Publicly accessible EBS snapshots pose a significant security risk, as attackers can restore and extract sensitive data if a snapshot is exposed. Misconfigured public snapshots have led to data breaches and compliance violations in the past. To mitigate this risk, EBS snapshots should be kept private or explicitly shared only with trusted AWS accounts, following least privilege principles to protect critical data and maintain security compliance.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.1.6", - "Description": "Ensure that ec2 common ports from instances are not internet-exposed", - "Checks": [ - "ec2_instance_port_cassandra_exposed_to_internet", - "ec2_instance_port_cifs_exposed_to_internet", - "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", - "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", - "ec2_instance_port_ssh_exposed_to_internet", - "ec2_instance_port_telnet_exposed_to_internet" - ], - "Attributes": [ - { - "Title": "Common ports from instances are not exposed", - "Section": "2. Attack Surface", - "SubSection": "2.1 Network", - "AttributeDescription": "Amazon EC2 instances can run various services that communicate over common ports such as 22 (SSH), 3389 (RDP), 80 (HTTP), and 443 (HTTPS) (and more). If these ports are open to the internet, attackers can attempt unauthorized access, brute-force attacks, or exploit known vulnerabilities. To reduce security risks, EC2 instances should be configured so that common ports are not exposed to the public internet, unless explicitly required and properly secured.", - "AdditionalInformation": "Exposing common ports directly to the internet increases the attack surface and risks unauthorized access or system compromise. Attackers frequently scan for open ports to target misconfigured or unpatched services. To enhance security, access to EC2 common ports should be restricted using security groups, network ACLs, and VPC configurations, ensuring that only trusted networks and users can connect.", - "LevelOfRisk": 5, - "Weight": 1000 - } - ] - }, - { - "Id": "2.1.7", - "Description": "Ensure that ec2 security groups do not allow ingress from internet to common ports", - "Checks": [ - "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23" - ], - "Attributes": [ - { - "Title": "Common ports from security groups do not allow ingress traffic", - "Section": "2. Attack Surface", - "SubSection": "2.1 Network", - "AttributeDescription": "Amazon EC2 security groups act as virtual firewalls, controlling inbound and outbound traffic to instances. If a security group allows ingress (incoming traffic) from the internet (0.0.0.0/0 or ::/0) to common ports such as 22 (SSH), 3389 (RDP), 80 (HTTP), or 443 (HTTPS) (and more), it creates a significant security risk. To minimize exposure, security groups should be configured to restrict ingress access to these ports to only trusted IP addresses or internal networks.", - "AdditionalInformation": "Allowing unrestricted inbound traffic to common ports increases the risk of brute-force attacks, unauthorized access, and exploitation of vulnerabilities. Attackers actively scan for open ports on public-facing EC2 instances to gain unauthorized control. To reduce security risks, ingress rules should be restricted using least privilege principles, IP whitelisting, VPN access, or bastion hosts, ensuring that only authorized users and networks can connect.", - "LevelOfRisk": 5, - "Weight": 1000 - } - ] - }, { "Id": "2.3.7", "Description": "Ensure there are no ECR repositories set as Public", @@ -976,114 +1120,6 @@ } ] }, - { - "Id": "2.2.9", - "Description": "Ensure EFS mount targets are not publicly accessible", - "Checks": [ - "efs_mount_target_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "No EFS mount targets are publicly accessible", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon Elastic File System (EFS) provides scalable, shared file storage for AWS services. EFS mount targets allow instances to connect to the file system within a VPC. By default, EFS mount targets can be configured with public accessibility, making them reachable from the internet. To enhance security, EFS mount targets should be restricted to private networks and should not be publicly accessible unless explicitly required and properly secured.", - "AdditionalInformation": "Publicly accessible EFS mount targets expose stored data to unauthorized access, cyberattacks, and data breaches. Attackers could exploit misconfigured security groups or network ACLs to access or modify files. To reduce security risks, EFS mount targets should be restricted to private subnets, with access limited to trusted VPCs, security groups, and IAM roles, ensuring secure file storage and controlled access.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "2.2.10", - "Description": "Ensure that EFS do not have policies which allow access to any client within the VPC", - "Checks": [ - "efs_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "No EFS have policies which allow access to any client within the VPC", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon Elastic File System (EFS) provides shared storage that can be accessed by multiple EC2 instances and services within a VPC. EFS access is controlled through resource-based policies that define which clients can connect. If an EFS policy allows access to any client within the VPC, it increases the risk of unauthorized access and data exposure. To enhance security, EFS policies should be restricted to specific IAM roles, security groups, or trusted resources instead of granting broad access to all VPC clients.", - "AdditionalInformation": "Allowing any client within a VPC to access an EFS file system increases the risk of data leaks, accidental modifications, or unauthorized access by compromised instances or misconfigured services. To minimize exposure, EFS policies should enforce least privilege access, restricting permissions to specific instances, roles, or users that require access, ensuring secure file storage and controlled data access.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "2.1.8", - "Description": "Ensure EKS cluster Network Policy is Enabled and Set as Appropriate", - "Checks": [ - "eks_cluster_network_policy_enabled" - ], - "Attributes": [ - { - "Title": "EKS cluster Network Policy is Enabled and Set as Appropriate", - "Section": "2. Attack Surface", - "SubSection": "2.1 Network", - "AttributeDescription": "A Network Policy defines how network traffic is controlled and restricted between workloads within a cloud environment. Enforcing network policies ensures that only authorized communication occurs between services, reducing the risk of unauthorized access and lateral movement. It is recommended to enable Network Policies and configure them appropriately to enforce least privilege access and secure communication between workloads.", - "AdditionalInformation": "Without properly configured Network Policies, workloads may be exposed to unnecessary or unauthorized network traffic, increasing the risk of data leaks, exploitation, or lateral movement by attackers. By enabling and enforcing Network Policies, organizations can limit communication between workloads, ensuring that only approved and necessary network interactions are allowed, minimizing the attack surface and enhancing overall security.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.1.9", - "Description": "Ensure EKS Clusters are not publicly accessible", - "Checks": [ - "eks_cluster_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "EKS Clusters are not publicly accessible", - "Section": "2. Attack Surface", - "SubSection": "2.1 Network", - "AttributeDescription": "Amazon Elastic Kubernetes Service (EKS) clusters manage containerized applications and can be configured with either private or public access. If an EKS cluster is publicly accessible, it means that the Kubernetes API endpoint can be reached from the internet, increasing the risk of unauthorized access and attacks. To enhance security, EKS clusters should be restricted to private networks and accessed only through secure VPNs, VPC peering, or AWS PrivateLink.", - "AdditionalInformation": "Exposing an EKS cluster to the public internet increases the risk of brute-force attacks, credential theft, and unauthorized access to Kubernetes workloads. Attackers could exploit misconfigured RBAC policies or API vulnerabilities to gain control over the cluster. To reduce security risks, EKS clusters should be configured with private endpoints, ensuring that only trusted networks and IAM-authenticated users can manage Kubernetes resources.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.1.10", - "Description": "Ensure EKS Clusters are created with Private Nodes", - "Checks": [ - "eks_cluster_private_nodes_enabled" - ], - "Attributes": [ - { - "Title": "EKS Clusters are created with Private Nodes", - "Section": "2. Attack Surface", - "SubSection": "2.1 Network", - "AttributeDescription": "Amazon Elastic Kubernetes Service (EKS) clusters run workloads on worker nodes, which can be either public or private. If EKS clusters are created with public nodes, these nodes are assigned public IP addresses, making them accessible from the internet, which increases the risk of unauthorized access and potential attacks. To enhance security, EKS clusters should be created with private nodes that operate within private subnets and are only accessible through secured networking configurations such as VPNs, VPC peering, or AWS PrivateLink.", - "AdditionalInformation": "Using public nodes in EKS exposes Kubernetes workloads to the internet, increasing the risk of unauthorized access, lateral movement, and potential exploitation. Attackers can target misconfigured workloads, open services, or unsecured API endpoints. By creating EKS clusters with private nodes, organizations can restrict access, limit exposure to public threats, and enforce network segmentation, ensuring that workloads remain secure and isolated within a private VPC environment.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.2.11", - "Description": "Ensure Elasticache Cluster is not using a public subnet", - "Checks": [ - "elasticache_cluster_uses_public_subnet" - ], - "Attributes": [ - { - "Title": "Elasticache Cluster is not using a public subnet", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon ElastiCache provides in-memory caching services using Redis and Memcached. By default, ElastiCache clusters can be deployed in either public or private subnets. If an ElastiCache cluster is placed in a public subnet, it becomes accessible from the internet, which significantly increases the risk of unauthorized access and data breaches. To enhance security, ElastiCache clusters should only be deployed in private subnets, ensuring restricted access within a VPC.", - "AdditionalInformation": "Deploying an ElastiCache cluster in a public subnet exposes it to external threats, such as unauthorized access, brute-force attacks, and potential data exfiltration. Attackers could exploit misconfigurations to access cached data or disrupt services. By restricting ElastiCache clusters to private subnets, organizations can limit access to trusted resources, enforce VPC security controls, and reduce the attack surface, ensuring secure and efficient caching operations.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, { "Id": "2.3.10", "Description": "Ensure no Elastic Load Balancers are facing internet", @@ -1156,42 +1192,6 @@ } ] }, - { - "Id": "2.2.12", - "Description": "Ensure S3 Glacier vaults have not policies which allow access to everyone", - "Checks": [ - "glacier_vaults_policy_public_access" - ], - "Attributes": [ - { - "Title": "S3 Glacier vaults have not policies which allow access to everyone", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon S3 Glacier provides low-cost, long-term storage for archival data. Glacier vaults can be configured with resource-based policies that control access. If a Glacier vault policy allows access to everyone, unauthorized users could retrieve or delete archived data, leading to data exposure or loss. To enhance security, Glacier vault policies should be restricted to specific AWS accounts, IAM roles, or trusted entities, ensuring only authorized users can access or manage archived data.", - "AdditionalInformation": "Allowing public access to S3 Glacier vaults poses a significant security risk, increasing the chance of data breaches, unauthorized deletions, or compliance violations. Attackers could restore and download sensitive archived data if the vault is misconfigured. To prevent unauthorized access, Glacier vaults should have strict access controls, using IAM policies, encryption, and resource-based permissions, ensuring that only trusted users and systems can interact with archived data.", - "LevelOfRisk": 5, - "Weight": 1000 - } - ] - }, - { - "Id": "2.2.13", - "Description": "Ensure Glue Data Catalogs are not publicly accessible", - "Checks": [ - "glue_data_catalogs_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "Glue Data Catalogs are not publicly accessible", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "AWS Glue Data Catalog is a centralized metadata repository used to store and manage schema information for data lakes and analytics workflows. By default, Glue Data Catalogs can be configured to allow public access, which poses a significant security risk if sensitive metadata is exposed. To enhance security, Glue Data Catalogs should be restricted to specific AWS accounts, IAM roles, or trusted services, ensuring that only authorized users can access or modify catalog information.", - "AdditionalInformation": "Allowing public access to Glue Data Catalogs increases the risk of unauthorized access, data leaks, and compliance violations. Attackers could gain insights into an organization’s data structure or modify catalog entries, leading to potential data corruption or unauthorized data exposure. To reduce security risks, Glue Data Catalogs should be secured using IAM policies, resource-based permissions, and AWS Lake Formation, ensuring that only trusted accounts and services can interact with metadata.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, { "Id": "2.3.14", "Description": "Ensure Kafka Cluster is not exposed to the public", @@ -1210,24 +1210,6 @@ } ] }, - { - "Id": "2.2.14", - "Description": "Ensure there are no internet exposed KMS keys", - "Checks": [ - "kms_key_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "No internet exposed KMS keys", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "AWS Key Management Service (KMS) provides secure encryption key management for data encryption and cryptographic operations. If KMS keys are exposed to the internet, unauthorized entities could potentially use, modify, or compromise encryption keys, leading to data breaches and security vulnerabilities. To enhance security, KMS keys should be restricted to trusted AWS accounts, IAM roles, and specific AWS services, ensuring that only authorized users and systems can access and manage them.", - "AdditionalInformation": "Exposing KMS keys to the public poses a critical security risk, as compromised keys can lead to unauthorized data decryption, loss of data integrity, and compliance violations. Attackers could potentially use public KMS keys to encrypt or decrypt sensitive data, undermining security controls. To prevent unauthorized access, KMS key policies should enforce strict access control using IAM permissions, VPC endpoint policies, and AWS PrivateLink, ensuring that encryption operations remain fully secured and isolated from the public internet.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, { "Id": "2.3.15", "Description": "Ensure lightsail database is not in public mode", @@ -1336,60 +1318,6 @@ } ] }, - { - "Id": "2.2.15", - "Description": "Ensure that S3 buckets have not policies which allow WRITE access", - "Checks": [ - "s3_bucket_policy_public_write_access" - ], - "Attributes": [ - { - "Title": "S3 buckets have not policies which allow WRITE access", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon S3 buckets store and manage data, files, and application assets. Bucket policies control access permissions, and if an S3 bucket has a policy that allows WRITE access to everyone, unauthorized users can upload, modify, or delete objects, leading to data tampering, security breaches, or service disruptions. To enhance security, S3 bucket policies should be restricted to specific AWS accounts, IAM roles, or trusted services, ensuring only authorized users have WRITE permissions.", - "AdditionalInformation": "Allowing unrestricted WRITE access to an S3 bucket increases the risk of unauthorized modifications, data injection attacks, and accidental data loss. Attackers could upload malicious files, delete critical data, or overwrite important configurations. To prevent unauthorized changes, S3 bucket policies should explicitly deny public WRITE access, enforce least privilege access control, and use AWS Block Public Access settings to ensure secure and controlled data storage.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.2.16", - "Description": "Ensure there are no S3 buckets listable by Everyone or Any AWS customer", - "Checks": [ - "s3_bucket_public_list_acl" - ], - "Attributes": [ - { - "Title": "No S3 buckets are listable by Everyone or Any AWS customer", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon S3 buckets store sensitive data and should have restricted access permissions. If an S3 bucket is listable by Everyone or Any AWS customer, unauthorized users can enumerate the objects within the bucket, potentially exposing sensitive information such as filenames, metadata, or even public datasets. To enhance security, S3 bucket permissions should be configured to restrict LIST access to only authorized IAM roles, AWS accounts, or specific services.", - "AdditionalInformation": "Allowing public or AWS-wide LIST access increases the risk of data enumeration, unauthorized access, and information leaks. Attackers or unauthorized users could identify and analyze stored files, extract metadata, or infer sensitive data. To mitigate this risk, S3 bucket policies should explicitly deny public LIST access, enforce least privilege permissions, and use AWS Block Public Access settings to prevent unintended data exposure.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, - { - "Id": "2.2.17", - "Description": "Ensure there are no S3 buckets writable by Everyone or Any AWS customer", - "Checks": [ - "s3_bucket_public_write_acl" - ], - "Attributes": [ - { - "Title": "No S3 buckets writable by Everyone or Any AWS customer", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "Amazon S3 buckets should have strict access controls to prevent unauthorized modifications. If an S3 bucket is writable by Everyone or Any AWS customer, it allows unauthorized users to upload, modify, or delete objects, leading to data corruption, security breaches, and compliance risks. To enhance security, S3 bucket permissions should be restricted to trusted IAM roles, AWS accounts, or specific services.", - "AdditionalInformation": "Allowing public or AWS-wide WRITE access creates a significant security risk, as attackers can inject malicious files, overwrite critical data, or delete essential objects. This could lead to data loss, malware distribution, or unauthorized system modifications. To prevent unauthorized changes, S3 bucket policies should explicitly deny public WRITE access, enforce least privilege access, and use AWS Block Public Access settings to secure data integrity and prevent unauthorized modifications.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, { "Id": "2.3.21", "Description": "Ensure Amazon SageMaker Notebook instances have not direct internet access", @@ -1408,24 +1336,6 @@ } ] }, - { - "Id": "2.2.18", - "Description": "Ensure Secrets Manager secrets are not publicly accessible", - "Checks": [ - "secretsmanager_not_publicly_accessible" - ], - "Attributes": [ - { - "Title": "Secrets Manager secrets are not publicly accessible", - "Section": "2. Attack Surface", - "SubSection": "2.2 Storage", - "AttributeDescription": "AWS Secrets Manager is used to securely store and manage sensitive information, such as API keys, database credentials, and encryption keys. By default, Secrets Manager secrets should be restricted to authorized IAM roles and AWS services. If a secret is publicly accessible, it can be exposed to unauthorized users, leading to data leaks, security breaches, and potential exploitation of sensitive credentials. To enhance security, Secrets Manager secrets should be strictly controlled using IAM policies and resource-based permissions.", - "AdditionalInformation": "Allowing public access to Secrets Manager secrets creates a critical security vulnerability, as attackers could retrieve, misuse, or exfiltrate sensitive information. Compromised secrets could lead to unauthorized access to databases, applications, or cloud services, resulting in data breaches, financial loss, or compliance violations. To mitigate this risk, Secrets Manager secrets should be restricted using least privilege IAM permissions, encrypted with AWS KMS, and accessed only by trusted AWS services and roles, ensuring secure and controlled secret management.", - "LevelOfRisk": 4, - "Weight": 100 - } - ] - }, { "Id": "2.3.22", "Description": "Ensure that SES identities are not publicly accessible", @@ -1516,24 +1426,6 @@ } ] }, - { - "Id": "3.3.1", - "Description": "Ensure AWS Config is enabled in all regions", - "Checks": [ - "config_recorder_all_regions_enabled" - ], - "Attributes": [ - { - "Title": "AWS Config is enabled", - "Section": "3. Logging and Monitoring", - "SubSection": "3.3 Monitoring", - "AttributeDescription": "AWS Config is a service that continuously monitors, records, and evaluates configuration changes in AWS resources within an account. It tracks configuration items, relationships between resources, and changes over time, delivering logs for security analysis, change management, and compliance auditing. To ensure comprehensive monitoring, AWS Config should be enabled in all regions.", - "AdditionalInformation": "Enabling AWS Config in all regions improves security, visibility, and compliance by: Tracking resource changes, allowing for quick identification of misconfigurations. Supporting security audits and forensic investigations by maintaining a historical record of configurations.", - "LevelOfRisk": 2, - "Weight": 8 - } - ] - }, { "Id": "3.1.3", "Description": "Ensure that server access logging is enabled on the CloudTrail S3 bucket", @@ -1552,42 +1444,6 @@ } ] }, - { - "Id": "4.2.3", - "Description": "Ensure CloudTrail logs are encrypted at rest using KMS CMKs", - "Checks": [ - "cloudtrail_kms_encryption_enabled" - ], - "Attributes": [ - { - "Title": "CloudTrail logs are encrypted at rest using KMS CMKs", - "Section": "4. Encryption", - "SubSection": "4.2 At-Rest", - "AttributeDescription": "AWS CloudTrail records API activity across an AWS account, and its logs contain sensitive security and operational data. AWS Key Management Service (KMS) provides encryption key management using customer-managed keys (CMKs) and Hardware Security Modules (HSMs) to ensure secure key storage and usage. CloudTrail logs can be encrypted using Server-Side Encryption (SSE) with KMS (SSE-KMS) to add an extra layer of protection and access control", - "AdditionalInformation": "Using SSE-KMS encryption for CloudTrail logs enhances security by adding an extra layer of access control. This ensures that only authorized users with both S3 read permissions and KMS decryption rights can access log data, protecting sensitive security information from unauthorized access or tampering. It also helps maintain compliance with security and regulatory standards by enforcing strict encryption controls.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, - { - "Id": "3.2.1", - "Description": "Ensure rotation for customer-created symmetric CMKs is enabled", - "Checks": [ - "kms_cmk_rotation_enabled" - ], - "Attributes": [ - { - "Title": "Rotation for customer-created symmetric CMKs enabled", - "Section": "3. Logging and Monitoring", - "SubSection": "3.2 Retention", - "AttributeDescription": "AWS Key Management Service (KMS) allows users to manage encryption keys securely. Key rotation enables the automatic replacement of the backing key (the cryptographic material tied to a customer-managed key (CMK)), ensuring continuous security without disrupting access to previously encrypted data. AWS automatically retains previous backing keys to allow seamless decryption of older data while using a newly generated key for encryption. It is recommended to enable key rotation for symmetric CMKs, as asymmetric keys do not support this feature.", - "AdditionalInformation": "Regularly rotating encryption keys minimizes the risk associated with key compromise by ensuring that newly encrypted data is protected with a fresh key, reducing the potential impact of an exposed key. Since AWS KMS retains prior backing keys for seamless decryption, rotation does not disrupt access to previously encrypted data. Implementing key rotation enhances security by limiting the exposure window of any single encryption key and aligning with best practices for cryptographic hygiene.", - "LevelOfRisk": 3, - "Weight": 10 - } - ] - }, { "Id": "3.1.4", "Description": "Ensure VPC flow logging is enabled in all VPCs", @@ -1642,6 +1498,60 @@ } ] }, + { + "Id": "3.2.1", + "Description": "Ensure rotation for customer-created symmetric CMKs is enabled", + "Checks": [ + "kms_cmk_rotation_enabled" + ], + "Attributes": [ + { + "Title": "Rotation for customer-created symmetric CMKs enabled", + "Section": "3. Logging and Monitoring", + "SubSection": "3.2 Retention", + "AttributeDescription": "AWS Key Management Service (KMS) allows users to manage encryption keys securely. Key rotation enables the automatic replacement of the backing key (the cryptographic material tied to a customer-managed key (CMK)), ensuring continuous security without disrupting access to previously encrypted data. AWS automatically retains previous backing keys to allow seamless decryption of older data while using a newly generated key for encryption. It is recommended to enable key rotation for symmetric CMKs, as asymmetric keys do not support this feature.", + "AdditionalInformation": "Regularly rotating encryption keys minimizes the risk associated with key compromise by ensuring that newly encrypted data is protected with a fresh key, reducing the potential impact of an exposed key. Since AWS KMS retains prior backing keys for seamless decryption, rotation does not disrupt access to previously encrypted data. Implementing key rotation enhances security by limiting the exposure window of any single encryption key and aligning with best practices for cryptographic hygiene.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "3.2.2", + "Description": "Ensure CloudWatch Log Groups have a retention policy of specific days", + "Checks": [ + "cloudwatch_log_group_retention_policy_specific_days_enabled" + ], + "Attributes": [ + { + "Title": "CloudWatch Log Groups have a retention policy of specific days", + "Section": "3. Logging and Monitoring", + "SubSection": "3.2 Retention", + "AttributeDescription": "AWS CloudWatch Log Groups store logs from various AWS services and applications, enabling monitoring, debugging, and security auditing. By default, CloudWatch logs are retained indefinitely, which can lead to unnecessary data storage costs and compliance risks. To manage log lifecycle effectively, it is recommended to set a retention policy for CloudWatch Log Groups, ensuring logs are retained only for a specific number of days based on operational and compliance requirements.", + "AdditionalInformation": "Setting a retention policy for CloudWatch logs helps balance cost management, compliance, and security. Retaining logs for too long increases storage costs and potential exposure to sensitive data, while keeping them for too short a duration can limit forensic investigations and compliance reporting. By defining a specific retention period, organizations can ensure logs are available for troubleshooting and audits while adhering to data retention best practices and regulatory requirements.", + "LevelOfRisk": 2, + "Weight": 8 + } + ] + }, + { + "Id": "3.3.1", + "Description": "Ensure AWS Config is enabled in all regions", + "Checks": [ + "config_recorder_all_regions_enabled" + ], + "Attributes": [ + { + "Title": "AWS Config is enabled", + "Section": "3. Logging and Monitoring", + "SubSection": "3.3 Monitoring", + "AttributeDescription": "AWS Config is a service that continuously monitors, records, and evaluates configuration changes in AWS resources within an account. It tracks configuration items, relationships between resources, and changes over time, delivering logs for security analysis, change management, and compliance auditing. To ensure comprehensive monitoring, AWS Config should be enabled in all regions.", + "AdditionalInformation": "Enabling AWS Config in all regions improves security, visibility, and compliance by: Tracking resource changes, allowing for quick identification of misconfigurations. Supporting security audits and forensic investigations by maintaining a historical record of configurations.", + "LevelOfRisk": 2, + "Weight": 8 + } + ] + }, { "Id": "3.3.2", "Description": "Ensure unauthorized API calls are monitored", @@ -1931,20 +1841,110 @@ ] }, { - "Id": "3.2.2", - "Description": "Ensure CloudWatch Log Groups have a retention policy of specific days", + "Id": "4.1.1", + "Description": "Ensure S3 Bucket Policy is set to deny HTTP requests", "Checks": [ - "cloudwatch_log_group_retention_policy_specific_days_enabled" + "s3_bucket_secure_transport_policy" ], "Attributes": [ { - "Title": "CloudWatch Log Groups have a retention policy of specific days", - "Section": "3. Logging and Monitoring", - "SubSection": "3.2 Retention", - "AttributeDescription": "AWS CloudWatch Log Groups store logs from various AWS services and applications, enabling monitoring, debugging, and security auditing. By default, CloudWatch logs are retained indefinitely, which can lead to unnecessary data storage costs and compliance risks. To manage log lifecycle effectively, it is recommended to set a retention policy for CloudWatch Log Groups, ensuring logs are retained only for a specific number of days based on operational and compliance requirements.", - "AdditionalInformation": "Setting a retention policy for CloudWatch logs helps balance cost management, compliance, and security. Retaining logs for too long increases storage costs and potential exposure to sensitive data, while keeping them for too short a duration can limit forensic investigations and compliance reporting. By defining a specific retention period, organizations can ensure logs are available for troubleshooting and audits while adhering to data retention best practices and regulatory requirements.", - "LevelOfRisk": 2, - "Weight": 8 + "Title": "S3 bucket deny HTTP requests", + "Section": "4. Encryption", + "SubSection": "4.1 In-Transit", + "AttributeDescription": "Amazon S3 bucket permissions can be configured using a bucket policy to enforce access restrictions. To enhance security, objects within the bucket should be made accessible only via HTTPS, ensuring encrypted data transmission.", + "AdditionalInformation": "By default, Amazon S3 accepts both HTTP and HTTPS requests, which can expose data to interception. To enforce secure access, HTTP requests should be explicitly denied in the bucket policy. Simply allowing HTTPS without blocking HTTP does not fully comply with security best practices, as unencrypted requests may still be accepted.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "4.1.2", + "Description": "Ensure that EC2 Metadata Service only allows IMDSv2", + "Checks": [ + "ec2_instance_imdsv2_enabled" + ], + "Attributes": [ + { + "Title": "EC2 Metadata Service only allows IMDSv2", + "Section": "4. Encryption", + "SubSection": "4.1 In-Transit", + "AttributeDescription": "AWS EC2 instances allow users to choose between Instance Metadata Service Version 1 (IMDSv1), which uses a request/response model, or Instance Metadata Service Version 2 (IMDSv2), which uses a session-based approach for enhanced security", + "AdditionalInformation": "Instance metadata refers to the data about an EC2 instance, such as host names, events, and security groups, that is used for managing and configuring the instance. When enabling the Metadata Service, users can opt for either IMDSv1, which operates via a simple request/response model, or IMDSv2, which implements session authentication for additional security. With IMDSv2, each request is secured by session-based authentication, ensuring that all interactions with the instance's metadata and credentials are protected. IMDSv1, on the other hand, may expose instances to Server-Side Request Forgery (SSRF) attacks. To improve security, Amazon recommends using IMDSv2", + "LevelOfRisk": 4, + "Weight": 100 + } + ] + }, + { + "Id": "4.1.3", + "Description": "Ensure that all expired SSL/TLS certificates stored in AWS IAM are removed", + "Checks": [ + "iam_no_expired_server_certificates_stored" + ], + "Attributes": [ + { + "Title": "Expired SSL/TLS certificates removed", + "Section": "4. Encryption", + "SubSection": "4.1 In-Transit", + "AttributeDescription": "To enable HTTPS connections for applications and websites hosted on AWS, an SSL/TLS server certificate is required. AWS provides two options for managing certificates: AWS Certificate Manager (ACM) – The preferred method for managing SSL/TLS certificates, automating renewals and deployment. IAM Certificate Storage – Used only when deploying SSL/TLS certificates in regions not supported by ACM. IAM securely encrypts private keys and stores them, but certificates must be obtained from an external provider. ACM certificates cannot be uploaded to IAM, and IAM certificates cannot be managed from the IAM Console.", + "AdditionalInformation": "Removing expired SSL/TLS certificates prevents the accidental deployment of invalid certificates, which could cause service disruptions, security warnings, and loss of credibility for applications using AWS services like Elastic Load Balancer (ELB). As a best practice, expired certificates should be deleted to maintain a secure and trusted application environment.", + "LevelOfRisk": 5, + "Weight": 1000 + } + ] + }, + { + "Id": "4.2.1", + "Description": "Ensure EBS volume encryption is enabled in all regions", + "Checks": [ + "ec2_ebs_volume_encryption" + ], + "Attributes": [ + { + "Title": "EBS volume encryption", + "Section": "4. Encryption", + "SubSection": "4.2 At-Rest", + "AttributeDescription": "Amazon Elastic Compute Cloud (EC2) supports encryption at rest for Elastic Block Store (EBS) volumes, ensuring that stored data remains protected. While EBS encryption is disabled by default, organizations can enforce automatic encryption of newly created volumes to enhance data security and compliance.", + "AdditionalInformation": "Enforcing EBS volume encryption reduces the risk of data exposure, unauthorized access, and compliance violations. If encryption remains intact, even if storage is compromised, data remains unreadable to unauthorized users. Encrypting data at rest ensures that sensitive information is protected against accidental disclosure, insider threats, and external attacks.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "4.2.2", + "Description": "Ensure that encryption-at-rest is enabled for RDS instances", + "Checks": [ + "rds_instance_storage_encrypted" + ], + "Attributes": [ + { + "Title": "RDS instances encryption at rest enabled", + "Section": "4. Encryption", + "SubSection": "4.2 At-Rest", + "AttributeDescription": "Amazon Relational Database Service (RDS) supports encryption at rest using the industry-standard AES-256 encryption algorithm to secure database instances and their associated storage. Once enabled, RDS encryption automatically handles access authentication and decryption, ensuring secure data storage with minimal performance impact.", + "AdditionalInformation": "Databases often contain sensitive and business-critical information, making encryption essential to protect against unauthorized access and data breaches. Enabling RDS encryption ensures that underlying storage, automated backups, read replicas, and snapshots are all encrypted, preventing accidental or malicious data exposure while maintaining compliance with security best practices.", + "LevelOfRisk": 3, + "Weight": 10 + } + ] + }, + { + "Id": "4.2.3", + "Description": "Ensure CloudTrail logs are encrypted at rest using KMS CMKs", + "Checks": [ + "cloudtrail_kms_encryption_enabled" + ], + "Attributes": [ + { + "Title": "CloudTrail logs are encrypted at rest using KMS CMKs", + "Section": "4. Encryption", + "SubSection": "4.2 At-Rest", + "AttributeDescription": "AWS CloudTrail records API activity across an AWS account, and its logs contain sensitive security and operational data. AWS Key Management Service (KMS) provides encryption key management using customer-managed keys (CMKs) and Hardware Security Modules (HSMs) to ensure secure key storage and usage. CloudTrail logs can be encrypted using Server-Side Encryption (SSE) with KMS (SSE-KMS) to add an extra layer of protection and access control", + "AdditionalInformation": "Using SSE-KMS encryption for CloudTrail logs enhances security by adding an extra layer of access control. This ensures that only authorized users with both S3 read permissions and KMS decryption rights can access log data, protecting sensitive security information from unauthorized access or tampering. It also helps maintain compliance with security and regulatory standards by enforcing strict encryption controls.", + "LevelOfRisk": 3, + "Weight": 10 } ] } From dcee114ef3b428a9480375f838e99314a9c81beb Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Mon, 11 Aug 2025 09:42:30 +0200 Subject: [PATCH 03/30] fix: validation errors in azure and m365 (#8368) --- prowler/CHANGELOG.md | 1 + .../admincenter/admincenter_service.py | 33 ++++++---- ...pam_outbound_policy_forwarding_disabled.py | 2 +- .../services/defender/defender_service.py | 60 +++++++++++++++++-- .../services/exchange/exchange_service.py | 12 +++- ...ntispam_outbound_policy_configured_test.py | 20 +++---- ...utbound_policy_forwarding_disabled_test.py | 20 +++---- .../defender/m365_defender_service_test.py | 8 +-- 8 files changed, 111 insertions(+), 45 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index cf2e158655..07e798ae8b 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Fixed - Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495) +- Validation errors in Azure and M365 providers [(#8353)](https://github.com/prowler-cloud/prowler/pull/8353) --- diff --git a/prowler/providers/m365/services/admincenter/admincenter_service.py b/prowler/providers/m365/services/admincenter/admincenter_service.py index 3a3e1f3284..1cd85faa2e 100644 --- a/prowler/providers/m365/services/admincenter/admincenter_service.py +++ b/prowler/providers/m365/services/admincenter/admincenter_service.py @@ -87,9 +87,11 @@ class AdminCenter(M365Service): { user.id: User( id=user.id, - name=user.display_name, + name=getattr(user, "display_name", ""), license=( - license_details.value[0].sku_part_number + getattr( + license_details.value[0], "sku_part_number", None + ) if license_details.value else None ), @@ -149,8 +151,8 @@ class AdminCenter(M365Service): { group.id: Group( id=group.id, - name=group.display_name, - visibility=group.visibility, + name=getattr(group, "display_name", ""), + visibility=getattr(group, "visibility", ""), ) } ) @@ -168,14 +170,21 @@ class AdminCenter(M365Service): domains_list = await self.client.domains.get() domains.update({}) for domain in domains_list.value: - domains.update( - { - domain.id: Domain( - id=domain.id, - password_validity_period=domain.password_validity_period_in_days, - ) - } - ) + if domain: + password_validity_period = getattr( + domain, "password_validity_period_in_days", None + ) + if password_validity_period is None: + password_validity_period = 0 + + domains.update( + { + domain.id: Domain( + id=domain.id, + password_validity_period=password_validity_period, + ) + } + ) except Exception as error: logger.error( diff --git a/prowler/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled.py b/prowler/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled.py index 04f81f62b3..b0530c4308 100644 --- a/prowler/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled.py +++ b/prowler/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled.py @@ -166,4 +166,4 @@ class defender_antispam_outbound_policy_forwarding_disabled(Check): policy.default or defender_client.outbound_spam_rules[policy.name].state.lower() == "enabled" - ) and not policy.auto_forwarding_mode + ) and policy.auto_forwarding_mode == "Off" diff --git a/prowler/providers/m365/services/defender/defender_service.py b/prowler/providers/m365/services/defender/defender_service.py index cdfd53a6b7..5d198b5888 100644 --- a/prowler/providers/m365/services/defender/defender_service.py +++ b/prowler/providers/m365/services/defender/defender_service.py @@ -44,6 +44,23 @@ class Defender(M365Service): malware_policy = [malware_policy] for policy in malware_policy: if policy: + file_types_raw = policy.get("FileTypes", []) + file_types = [] + if file_types_raw is not None: + if isinstance(file_types_raw, list): + file_types = file_types_raw + else: + try: + if isinstance(file_types_raw, str): + file_types = [file_types_raw] + else: + file_types = [str(file_types_raw)] + except (ValueError, TypeError): + logger.warning( + f"Skipping invalid file_types value: {file_types_raw}" + ) + file_types = [] + malware_policies.append( MalwarePolicy( enable_file_filter=policy.get("EnableFileFilter", False), @@ -54,7 +71,7 @@ class Defender(M365Service): internal_sender_admin_address=policy.get( "InternalSenderAdminAddress", "" ), - file_types=policy.get("FileTypes", []), + file_types=file_types, is_default=policy.get("IsDefault", False), ) ) @@ -207,7 +224,7 @@ class Defender(M365Service): notify_sender_blocked_addresses=policy.get( "NotifyOutboundSpamRecipients", [] ), - auto_forwarding_mode=policy.get("AutoForwardingMode", True), + auto_forwarding_mode=policy.get("AutoForwardingMode", "On"), default=policy.get("IsDefault", False), ) @@ -257,12 +274,43 @@ class Defender(M365Service): inbound_spam_policy = [inbound_spam_policy] for policy in inbound_spam_policy: if policy: + allowed_domains_raw = policy.get("AllowedSenderDomains", []) + allowed_domains = [] + + if isinstance(allowed_domains_raw, str): + try: + import json + + parsed_domains = json.loads(allowed_domains_raw) + if isinstance(parsed_domains, list): + allowed_domains_raw = parsed_domains + else: + logger.warning( + f"Expected list from JSON string, got: {type(parsed_domains)}" + ) + allowed_domains_raw = [] + except (json.JSONDecodeError, ValueError) as e: + logger.warning( + f"Failed to parse AllowedSenderDomains as JSON: {e}" + ) + allowed_domains_raw = [] + + if allowed_domains_raw: + for domain in allowed_domains_raw: + if isinstance(domain, str): + allowed_domains.append(domain) + else: + try: + allowed_domains.append(str(domain)) + except (ValueError, TypeError): + logger.warning( + f"Skipping invalid domain value: {domain}" + ) + inbound_spam_policies.append( DefenderInboundSpamPolicy( identity=policy.get("Identity", ""), - allowed_sender_domains=policy.get( - "AllowedSenderDomains", [] - ), + allowed_sender_domains=allowed_domains, default=policy.get("IsDefault", False), ) ) @@ -389,7 +437,7 @@ class OutboundSpamPolicy(BaseModel): notify_limit_exceeded: bool notify_limit_exceeded_addresses: List[str] notify_sender_blocked_addresses: List[str] - auto_forwarding_mode: bool + auto_forwarding_mode: str default: bool diff --git a/prowler/providers/m365/services/exchange/exchange_service.py b/prowler/providers/m365/services/exchange/exchange_service.py index 96bbd4e13c..35d4068007 100644 --- a/prowler/providers/m365/services/exchange/exchange_service.py +++ b/prowler/providers/m365/services/exchange/exchange_service.py @@ -123,12 +123,20 @@ class Exchange(M365Service): rules_data = [rules_data] for rule in rules_data: if rule: + sender_domain_is = rule.get("SenderDomainIs", []) + if sender_domain_is is None: + sender_domain_is = [] + + redirect_message_to = rule.get("RedirectMessageTo", []) + if redirect_message_to is None: + redirect_message_to = [] + transport_rules.append( TransportRule( name=rule.get("Name", ""), scl=rule.get("SetSCL", None), - sender_domain_is=rule.get("SenderDomainIs", []), - redirect_message_to=rule.get("RedirectMessageTo", None), + sender_domain_is=sender_domain_is, + redirect_message_to=redirect_message_to, ) ) except Exception as error: diff --git a/tests/providers/m365/services/defender/defender_antispam_outbound_policy_configured/defender_antispam_outbound_policy_configured_test.py b/tests/providers/m365/services/defender/defender_antispam_outbound_policy_configured/defender_antispam_outbound_policy_configured_test.py index 7baedbeb61..c3200b2e36 100644 --- a/tests/providers/m365/services/defender/defender_antispam_outbound_policy_configured/defender_antispam_outbound_policy_configured_test.py +++ b/tests/providers/m365/services/defender/defender_antispam_outbound_policy_configured/defender_antispam_outbound_policy_configured_test.py @@ -36,7 +36,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], notify_sender_blocked_addresses=["admin@example.com"], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=True, ) } @@ -93,7 +93,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], notify_sender_blocked_addresses=["admin@example.com"], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=True, ), "Policy1": OutboundSpamPolicy( @@ -102,7 +102,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], notify_sender_blocked_addresses=["admin@example.com"], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=False, ), } @@ -177,7 +177,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], notify_sender_blocked_addresses=["admin@example.com"], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=True, ), "Policy1": OutboundSpamPolicy( @@ -186,7 +186,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=False, notify_limit_exceeded_addresses=[], notify_sender_blocked_addresses=[], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=False, ), } @@ -261,7 +261,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=False, notify_limit_exceeded_addresses=[], notify_sender_blocked_addresses=[], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=True, ), "Policy1": OutboundSpamPolicy( @@ -270,7 +270,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], notify_sender_blocked_addresses=["admin@example.com"], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=False, ), } @@ -344,7 +344,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=False, notify_limit_exceeded_addresses=[], notify_sender_blocked_addresses=[], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=True, ) } @@ -398,7 +398,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=False, notify_limit_exceeded_addresses=[], notify_sender_blocked_addresses=[], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=True, ), "Policy1": OutboundSpamPolicy( @@ -407,7 +407,7 @@ class Test_defender_antispam_outbound_policy_configured: notify_sender_blocked=False, notify_limit_exceeded_addresses=[], notify_sender_blocked_addresses=[], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=False, ), } diff --git a/tests/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled_test.py b/tests/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled_test.py index 64fce5f88b..72f5c104ff 100644 --- a/tests/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled_test.py +++ b/tests/providers/m365/services/defender/defender_antispam_outbound_policy_forwarding_disabled/defender_antispam_outbound_policy_forwarding_disabled_test.py @@ -32,7 +32,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: defender_client.outbound_spam_policies = { "Default": OutboundSpamPolicy( name="Default", - auto_forwarding_mode=False, + auto_forwarding_mode="Off", notify_limit_exceeded=True, notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], @@ -86,7 +86,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: defender_client.outbound_spam_policies = { "Default": OutboundSpamPolicy( name="Default", - auto_forwarding_mode=False, + auto_forwarding_mode="Off", notify_limit_exceeded=True, notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], @@ -95,7 +95,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: ), "Policy1": OutboundSpamPolicy( name="Policy1", - auto_forwarding_mode=False, + auto_forwarding_mode="Off", notify_limit_exceeded=True, notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], @@ -172,7 +172,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: defender_client.outbound_spam_policies = { "Default": OutboundSpamPolicy( name="Default", - auto_forwarding_mode=False, + auto_forwarding_mode="Off", notify_limit_exceeded=True, notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], @@ -181,7 +181,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: ), "Policy1": OutboundSpamPolicy( name="Policy1", - auto_forwarding_mode=True, + auto_forwarding_mode="On", notify_limit_exceeded=False, notify_sender_blocked=False, notify_limit_exceeded_addresses=[], @@ -258,7 +258,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: defender_client.outbound_spam_policies = { "Default": OutboundSpamPolicy( name="Default", - auto_forwarding_mode=True, + auto_forwarding_mode="On", notify_limit_exceeded=False, notify_sender_blocked=False, notify_limit_exceeded_addresses=[], @@ -267,7 +267,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: ), "Policy1": OutboundSpamPolicy( name="Policy1", - auto_forwarding_mode=False, + auto_forwarding_mode="Off", notify_limit_exceeded=True, notify_sender_blocked=True, notify_limit_exceeded_addresses=["admin@example.com"], @@ -343,7 +343,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: defender_client.outbound_spam_policies = { "Default": OutboundSpamPolicy( name="Default", - auto_forwarding_mode=True, + auto_forwarding_mode="On", notify_limit_exceeded=False, notify_sender_blocked=False, notify_limit_exceeded_addresses=[], @@ -397,7 +397,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: defender_client.outbound_spam_policies = { "Default": OutboundSpamPolicy( name="Default", - auto_forwarding_mode=True, + auto_forwarding_mode="On", notify_limit_exceeded=False, notify_sender_blocked=False, notify_limit_exceeded_addresses=[], @@ -406,7 +406,7 @@ class Test_defender_antispam_outbound_policy_forwarding_disabled: ), "Policy1": OutboundSpamPolicy( name="Policy1", - auto_forwarding_mode=True, + auto_forwarding_mode="On", notify_limit_exceeded=False, notify_sender_blocked=False, notify_limit_exceeded_addresses=[], diff --git a/tests/providers/m365/services/defender/m365_defender_service_test.py b/tests/providers/m365/services/defender/m365_defender_service_test.py index 35534a53e3..a78cc4b10a 100644 --- a/tests/providers/m365/services/defender/m365_defender_service_test.py +++ b/tests/providers/m365/services/defender/m365_defender_service_test.py @@ -180,7 +180,7 @@ def mock_defender_get_outbound_spam_filter_policy(_): notify_limit_exceeded=True, notify_limit_exceeded_addresses=["security@example.com"], notify_sender_blocked_addresses=["security@example.com"], - auto_forwarding_mode=False, + auto_forwarding_mode="Off", default=False, ), "Policy2": OutboundSpamPolicy( @@ -189,7 +189,7 @@ def mock_defender_get_outbound_spam_filter_policy(_): notify_limit_exceeded=False, notify_limit_exceeded_addresses=[], notify_sender_blocked_addresses=[], - auto_forwarding_mode=True, + auto_forwarding_mode="On", default=True, ), } @@ -438,7 +438,7 @@ class Test_Defender_Service: assert outbound_spam_policies[ "Policy1" ].notify_sender_blocked_addresses == ["security@example.com"] - assert outbound_spam_policies["Policy1"].auto_forwarding_mode is False + assert outbound_spam_policies["Policy1"].auto_forwarding_mode == "Off" assert outbound_spam_policies["Policy1"].default is False assert outbound_spam_policies["Policy2"].name == "Policy2" assert outbound_spam_policies["Policy2"].notify_sender_blocked is False @@ -449,7 +449,7 @@ class Test_Defender_Service: assert ( outbound_spam_policies["Policy2"].notify_sender_blocked_addresses == [] ) - assert outbound_spam_policies["Policy2"].auto_forwarding_mode is True + assert outbound_spam_policies["Policy2"].auto_forwarding_mode == "On" assert outbound_spam_policies["Policy2"].default is True defender_client.powershell.close() From 85af4ff77c162287ed832e012968ba2bb13f73e6 Mon Sep 17 00:00:00 2001 From: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> Date: Mon, 11 Aug 2025 09:47:56 +0200 Subject: [PATCH 04/30] feat(m365): add certificate auth method to cli (#8404) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 2 +- prowler/providers/common/provider.py | 2 + .../providers/m365/exceptions/exceptions.py | 33 + .../providers/m365/lib/arguments/arguments.py | 11 + .../m365/lib/powershell/m365_powershell.py | 209 ++- prowler/providers/m365/m365_provider.py | 355 ++++- prowler/providers/m365/models.py | 4 +- .../m365/lib/arguments/m365_arguments_test.py | 641 ++++++++ .../lib/powershell/m365_powershell_test.py | 760 ++++++++- tests/providers/m365/m365_fixtures.py | 3 +- tests/providers/m365/m365_provider_test.py | 1397 ++++++++++++++++- 11 files changed, 3258 insertions(+), 159 deletions(-) create mode 100644 tests/providers/m365/lib/arguments/m365_arguments_test.py diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 07e798ae8b..2a1428ef18 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -2,10 +2,10 @@ All notable changes to the **Prowler SDK** are documented in this file. - ## [v5.11.0] (Prowler UNRELEASED) ### Added +- Certificate authentication for M365 provider [(#8404)](https://github.com/prowler-cloud/prowler/pull/8404) ### Changed diff --git a/prowler/providers/common/provider.py b/prowler/providers/common/provider.py index f0e233017b..5f3ee07160 100644 --- a/prowler/providers/common/provider.py +++ b/prowler/providers/common/provider.py @@ -222,6 +222,8 @@ class Provider(ABC): env_auth=arguments.env_auth, az_cli_auth=arguments.az_cli_auth, browser_auth=arguments.browser_auth, + certificate_auth=arguments.certificate_auth, + certificate_path=arguments.certificate_path, tenant_id=arguments.tenant_id, init_modules=arguments.init_modules, fixer_config=fixer_config, diff --git a/prowler/providers/m365/exceptions/exceptions.py b/prowler/providers/m365/exceptions/exceptions.py index 7f9dae2c31..871607aeff 100644 --- a/prowler/providers/m365/exceptions/exceptions.py +++ b/prowler/providers/m365/exceptions/exceptions.py @@ -126,6 +126,18 @@ class M365BaseException(ProwlerException): "message": "Failed to establish connection to Exchange Online API.", "remediation": "Ensure the application has proper permission granted to access Exchange Online.", }, + (6030, "M365CertificateCreationError"): { + "message": "Failed to create X.509 certificate object from provided certificate content.", + "remediation": "Ensure the certificate content is valid base64 encoded X.509 certificate data and is properly formatted.", + }, + (6031, "M365NotValidCertificateContentError"): { + "message": "The provided certificate content is not valid base64 encoded data.", + "remediation": "Ensure the certificate content is valid base64 encoded X.509 certificate data without line breaks or invalid characters.", + }, + (6032, "M365NotValidCertificatePathError"): { + "message": "The provided certificate path is not valid or the file cannot be accessed.", + "remediation": "Ensure the certificate path exists, is accessible, and points to a valid certificate file.", + }, } def __init__(self, code, file=None, original_exception=None, message=None): @@ -357,3 +369,24 @@ class M365ExchangeConnectionError(M365CredentialsError): super().__init__( 6029, file=file, original_exception=original_exception, message=message ) + + +class M365CertificateCreationError(M365CredentialsError): + def __init__(self, file=None, original_exception=None, message=None): + super().__init__( + 6030, file=file, original_exception=original_exception, message=message + ) + + +class M365NotValidCertificateContentError(M365CredentialsError): + def __init__(self, file=None, original_exception=None, message=None): + super().__init__( + 6031, file=file, original_exception=original_exception, message=message + ) + + +class M365NotValidCertificatePathError(M365CredentialsError): + def __init__(self, file=None, original_exception=None, message=None): + super().__init__( + 6032, file=file, original_exception=original_exception, message=message + ) diff --git a/prowler/providers/m365/lib/arguments/arguments.py b/prowler/providers/m365/lib/arguments/arguments.py index e88ef7982b..fffbc3e5bb 100644 --- a/prowler/providers/m365/lib/arguments/arguments.py +++ b/prowler/providers/m365/lib/arguments/arguments.py @@ -28,6 +28,17 @@ def init_parser(self): action="store_true", help="Use Azure interactive browser authentication to log in against Microsoft 365", ) + m365_auth_modes_group.add_argument( + "--certificate-auth", + action="store_true", + help="Use Certificate authentication to log in against Microsoft 365", + ) + m365_parser.add_argument( + "--certificate-path", + nargs="?", + default=None, + help="Path to the certificate file to be used with --certificate-auth option", + ) m365_parser.add_argument( "--tenant-id", nargs="?", diff --git a/prowler/providers/m365/lib/powershell/m365_powershell.py b/prowler/providers/m365/lib/powershell/m365_powershell.py index 7692700988..3cd2dda4df 100644 --- a/prowler/providers/m365/lib/powershell/m365_powershell.py +++ b/prowler/providers/m365/lib/powershell/m365_powershell.py @@ -4,6 +4,7 @@ import platform from prowler.lib.logger import logger from prowler.lib.powershell.powershell import PowerShellSession from prowler.providers.m365.exceptions.exceptions import ( + M365CertificateCreationError, M365GraphConnectionError, M365UserCredentialsError, M365UserNotBelongingToTenantError, @@ -51,23 +52,71 @@ class M365PowerShell(PowerShellSession): self.tenant_identity = identity self.init_credential(credentials) + def clean_certificate_content(self, cert_content: str) -> str: + """ + Clean certificate content for PowerShell consumption. + + Removes newlines, carriage returns, and extra spaces from base64 content + to ensure proper parsing in PowerShell. + + Args: + cert_content (str): Base64 encoded certificate content + + Returns: + str: Cleaned base64 certificate content + """ + # Clean base64 content - remove any newlines or whitespace + clean_content = ( + cert_content.strip().replace("\n", "").replace("\r", "").replace(" ", "") + ) + logger.info(f"Cleaned certificate content length: {len(clean_content)}") + return clean_content + def init_credential(self, credentials: M365Credentials) -> None: """ Initialize PowerShell credential object for Microsoft 365 authentication. - Sanitizes the username and password, then creates a PSCredential object - in the PowerShell session for use with Microsoft 365 cmdlets. + Supports three authentication methods: + 1. User authentication (username/password) - Will be deprecated in September 2025 + 2. Application authentication (client_id/client_secret) + 3. Certificate authentication (certificate_content in base64/application_id) Args: credentials (M365Credentials): The credentials object containing - username and password. + authentication information. Note: The credentials are sanitized to prevent command injection and stored securely in the PowerShell session. """ + # Certificate Auth + if credentials.certificate_content and credentials.client_id: + # Clean certificate content for PowerShell consumption + clean_cert_content = self.clean_certificate_content( + credentials.certificate_content + ) + + # Sanitize credentials + sanitized_client_id = self.sanitize(credentials.client_id) + sanitized_tenant_id = self.sanitize(credentials.tenant_id) + + self.execute( + f'$certBytes = [Convert]::FromBase64String("{clean_cert_content}")' + ) + error = self.execute( + "$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(,$certBytes)" + ) + if error: + raise M365CertificateCreationError( + f"[{os.path.basename(__file__)}] Error creating certificate: {error}" + ) + + self.execute(f'$clientID = "{sanitized_client_id}"') + self.execute(f'$tenantID = "{sanitized_tenant_id}"') + self.execute(f'$tenantDomain = "{credentials.tenant_domains[0]}"') + # User Auth (Will be deprecated in September 2025) - if credentials.user and credentials.passwd: + elif credentials.user and credentials.passwd: credentials.encrypted_passwd = self.encrypt_password(credentials.passwd) # Sanitize user and password @@ -135,14 +184,28 @@ class M365PowerShell(PowerShellSession): """ Test Microsoft 365 credentials by attempting to authenticate against Entra ID. + Supports testing three authentication methods: + 1. User authentication (username/password) + 2. Application authentication (client_id/client_secret) + 3. Certificate authentication (certificate_content in base64/application_id) + Args: credentials (M365Credentials): The credentials object containing - username and password to test. + authentication information to test. Returns: bool: True if credentials are valid and authentication succeeds, False otherwise. """ - if credentials.user and credentials.passwd: + # Test Certificate Auth + if credentials.certificate_content and credentials.client_id: + try: + self.test_teams_certificate_connection() or self.test_exchange_certificate_connection() + return True + except Exception as e: + logger.error(f"Exchange Online Certificate connection failed: {e}") + + # Test User Auth + elif credentials.user and credentials.passwd: self.execute( f'$securePassword = "{credentials.encrypted_passwd}" | ConvertTo-SecureString' # encrypted password already sanitized ) @@ -161,6 +224,7 @@ class M365PowerShell(PowerShellSession): ) # Validate credentials + # Test Exchange Online connection result = self.execute("Connect-ExchangeOnline -Credential $credential") if "https://aka.ms/exov3-module" not in result: if "AADSTS" in result: # Entra Security Token Service Error @@ -168,21 +232,19 @@ class M365PowerShell(PowerShellSession): file=os.path.basename(__file__), message=result, ) - else: # Could not connect to Exchange Online, try Microsoft Teams - result = self.execute( - "Connect-MicrosoftTeams -Credential $credential" - ) - if self.tenant_identity.tenant_id not in result: - if "AADSTS" in result: # Entra Security Token Service Error - raise M365UserCredentialsError( - file=os.path.basename(__file__), - message=result, - ) - else: # Unknown error, could be a permission issue or modules not installed - raise Exception( - file=os.path.basename(__file__), - message=f"Error connecting to PowerShell modules: {result}", - ) + # Test Microsoft Teams connection + result = self.execute("Connect-MicrosoftTeams -Credential $credential") + if self.tenant_identity.user not in result: + if "AADSTS" in result: # Entra Security Token Service Error + raise M365UserCredentialsError( + file=os.path.basename(__file__), + message=result, + ) + else: # Unknown error, could be a permission issue or modules not installed + raise M365UserCredentialsError( + file=os.path.basename(__file__), + message=f"Error connecting to PowerShell modules: {result if result else 'Unknown error'}", + ) return True @@ -235,6 +297,9 @@ class M365PowerShell(PowerShellSession): "Microsoft Teams connection failed: Please check your permissions and try again." ) return False + self.execute( + 'Connect-MicrosoftTeams -AccessTokens @("$graphToken","$teamsToken")' + ) return True except Exception as e: logger.error( @@ -242,6 +307,31 @@ class M365PowerShell(PowerShellSession): ) return False + def test_teams_certificate_connection(self) -> bool: + """Test Microsoft Teams API connection using certificate and raise exception if it fails.""" + result = self.execute( + "Connect-MicrosoftTeams -Certificate $certificate -ApplicationId $clientID -TenantId $tenantID" + ) + if self.tenant_identity.identity_id not in result: + logger.error(f"Microsoft Teams Certificate connection failed: {result}") + return False + return True + + def test_teams_user_connection(self) -> bool: + """Test Microsoft Teams API connection using user authentication and raise exception if it fails.""" + result = self.execute("Connect-MicrosoftTeams -Credential $credential") + if self.tenant_identity.user not in result: + logger.error(f"Microsoft Teams User Auth connection failed: {result}.") + return False + + connection = self.execute("Get-CsTeamsClientConfiguration") + if not connection: + logger.error( + "Microsoft Teams User Auth connection failed: Please check your permissions and try again." + ) + return False + return True + def test_exchange_connection(self) -> bool: """Test Exchange Online API connection and raise exception if it fails.""" try: @@ -258,6 +348,9 @@ class M365PowerShell(PowerShellSession): "Exchange Online connection failed: Please check your permissions and try again." ) return False + self.execute( + 'Connect-ExchangeOnline -AccessToken $exchangeToken.AccessToken -Organization "$tenantID"' + ) return True except Exception as e: logger.error( @@ -265,11 +358,40 @@ class M365PowerShell(PowerShellSession): ) return False + def test_exchange_certificate_connection(self) -> bool: + """Test Exchange Online API connection using certificate and raise exception if it fails.""" + result = self.execute( + "Connect-ExchangeOnline -Certificate $certificate -AppId $clientID -Organization $tenantDomain" + ) + if "https://aka.ms/exov3-module" not in result: + logger.error(f"Exchange Online Certificate connection failed: {result}") + return False + return True + + def test_exchange_user_connection(self) -> bool: + """Test Exchange Online API connection using user authentication and raise exception if it fails.""" + result = self.execute("Connect-ExchangeOnline -Credential $credential") + if "https://aka.ms/exov3-module" not in result: + logger.error(f"Exchange Online User Auth connection failed: {result}.") + return False + + connection = self.execute("Get-OrganizationConfig") + if not connection: + logger.error( + "Exchange Online User Auth connection failed: Please check your permissions and try again." + ) + return False + return True + def connect_microsoft_teams(self) -> dict: """ Connect to Microsoft Teams Module PowerShell Module. Establishes a connection to Microsoft Teams using the initialized credentials. + Supports three authentication methods: + 1. User authentication (username/password) + 2. Application authentication (client_id/client_secret) + 3. Certificate authentication (certificate_content in base64/application_id) Returns: dict: Connection status information in JSON format. @@ -277,26 +399,15 @@ class M365PowerShell(PowerShellSession): Note: This method requires the Microsoft Teams PowerShell module to be installed. """ + # Certificate Auth + if self.execute("Write-Output $certificate") != "": + return self.test_teams_certificate_connection() # User Auth if self.execute("Write-Output $credential") != "": - self.execute("Connect-MicrosoftTeams -Credential $credential") - # Test connection with a simple call - connection = self.execute("Get-CsTeamsClientConfiguration") - if connection: - return True - else: - logger.error( - "Microsoft Teams User Auth connection failed: Please check your permissions and try again." - ) - return connection + return self.test_teams_user_connection() # Application Auth else: - connection = self.test_teams_connection() - if connection: - self.execute( - 'Connect-MicrosoftTeams -AccessTokens @("$graphToken","$teamsToken")' - ) - return connection + return self.test_teams_connection() def get_teams_settings(self) -> dict: """ @@ -383,6 +494,10 @@ class M365PowerShell(PowerShellSession): Connect to Exchange Online PowerShell Module. Establishes a connection to Exchange Online using the initialized credentials. + Supports three authentication methods: + 1. User authentication (username/password) + 2. Application authentication (client_id/client_secret) + 3. Certificate authentication (certificate_content in base64/application_id) Returns: dict: Connection status information in JSON format. @@ -390,25 +505,15 @@ class M365PowerShell(PowerShellSession): Note: This method requires the Exchange Online PowerShell module to be installed. """ + # Certificate Auth + if self.execute("Write-Output $certificate") != "": + return self.test_exchange_certificate_connection() # User Auth if self.execute("Write-Output $credential") != "": - self.execute("Connect-ExchangeOnline -Credential $credential") - connection = self.execute("Get-OrganizationConfig") - if connection: - return True - else: - logger.error( - "Exchange Online User Auth connection failed: Please check your permissions and try again." - ) - return False + return self.test_exchange_user_connection() # Application Auth else: - connection = self.test_exchange_connection() - if connection: - self.execute( - 'Connect-ExchangeOnline -AccessToken $exchangeToken.AccessToken -Organization "$tenantID"' - ) - return connection + return self.test_exchange_connection() def get_audit_log_config(self) -> dict: """ diff --git a/prowler/providers/m365/m365_provider.py b/prowler/providers/m365/m365_provider.py index 1910e5de91..4be03f5a70 100644 --- a/prowler/providers/m365/m365_provider.py +++ b/prowler/providers/m365/m365_provider.py @@ -1,4 +1,5 @@ import asyncio +import base64 import os from argparse import ArgumentTypeError from os import getenv @@ -6,6 +7,7 @@ from uuid import UUID from azure.core.exceptions import ClientAuthenticationError, HttpResponseError from azure.identity import ( + CertificateCredential, ClientSecretCredential, CredentialUnavailableError, DefaultAzureCredential, @@ -41,6 +43,8 @@ from prowler.providers.m365.exceptions.exceptions import ( M365MissingEnvironmentCredentialsError, M365NoAuthenticationMethodError, M365NotTenantIdButClientIdAndClientSecretError, + M365NotValidCertificateContentError, + M365NotValidCertificatePathError, M365NotValidClientIdError, M365NotValidClientSecretError, M365NotValidTenantIdError, @@ -111,11 +115,14 @@ class M365Provider(Provider): env_auth: bool = False, az_cli_auth: bool = False, browser_auth: bool = False, + certificate_auth: bool = False, tenant_id: str = None, client_id: str = None, client_secret: str = None, user: str = None, password: str = None, + certificate_content: str = None, + certificate_path: str = None, init_modules: bool = False, region: str = "M365Global", config_content: dict = None, @@ -158,11 +165,14 @@ class M365Provider(Provider): sp_env_auth, env_auth, browser_auth, + certificate_auth, tenant_id, client_id, client_secret, user, password, + certificate_content, + certificate_path, ) logger.info("Checking if region is different than default one") @@ -170,13 +180,15 @@ class M365Provider(Provider): # Get the dict from the static credentials m365_credentials = None - if tenant_id and client_id and client_secret: + if tenant_id and client_id: m365_credentials = self.validate_static_credentials( tenant_id=tenant_id, client_id=client_id, client_secret=client_secret, user=user, password=password, + certificate_content=certificate_content, + certificate_path=certificate_path, ) # Set up the M365 session @@ -185,6 +197,8 @@ class M365Provider(Provider): sp_env_auth, env_auth, browser_auth, + certificate_auth, + certificate_path, tenant_id, m365_credentials, self._region_config, @@ -196,6 +210,7 @@ class M365Provider(Provider): env_auth, browser_auth, az_cli_auth, + certificate_auth, self._session, ) @@ -203,6 +218,8 @@ class M365Provider(Provider): self._credentials = self.setup_powershell( env_auth=env_auth, sp_env_auth=sp_env_auth, + certificate_auth=certificate_auth, + certificate_path=certificate_path, m365_credentials=m365_credentials, identity=self.identity, init_modules=init_modules, @@ -279,11 +296,14 @@ class M365Provider(Provider): sp_env_auth: bool, env_auth: bool, browser_auth: bool, + certificate_auth: bool, tenant_id: str, client_id: str, client_secret: str, user: str, password: str, + certificate_content: str, + certificate_path: str, ): """ Validates the authentication arguments for the M365 provider. @@ -293,11 +313,14 @@ class M365Provider(Provider): sp_env_auth (bool): Flag indicating whether application authentication with environment variables is enabled. env_auth: (bool): Flag indicating whether to use application and PowerShell authentication with environment variables. browser_auth (bool): Flag indicating whether browser authentication is enabled. + certificate_auth (bool): Flag indicating whether certificate authentication is enabled. tenant_id (str): The M365 Tenant ID. client_id (str): The M365 Client ID. client_secret (str): The M365 Client Secret. user (str): The M365 User Account. password (str): The M365 User Password. + certificate_content (str): The M365 Certificate Content. + certificate_path (str): The path to the certificate file. Raises: M365BrowserAuthNoTenantIDError: If browser authentication is enabled but the tenant ID is not found. @@ -314,28 +337,33 @@ class M365Provider(Provider): and not sp_env_auth and not browser_auth and not env_auth + and not certificate_auth ): raise M365NoAuthenticationMethodError( file=os.path.basename(__file__), - message="M365 provider requires at least one authentication method set: [--env-auth | --az-cli-auth | --sp-env-auth | --browser-auth]", + message="M365 provider requires at least one authentication method set: [--env-auth | --az-cli-auth | --sp-env-auth | --browser-auth | --certificate-auth]", ) elif browser_auth and not tenant_id: raise M365BrowserAuthNoTenantIDError( file=os.path.basename(__file__), message="M365 Tenant ID (--tenant-id) is required for browser authentication mode", ) - elif env_auth: - if not user or not password or not tenant_id: - raise M365MissingEnvironmentCredentialsError( - file=os.path.basename(__file__), - message="M365 provider requires AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID, M365_USER and M365_PASSWORD environment variables to be set when using --env-auth", - ) else: if not tenant_id: raise M365NotTenantIdButClientIdAndClientSecretError( file=os.path.basename(__file__), message="Tenant Id is required for M365 static credentials. Make sure you are using the correct credentials.", ) + if ( + not certificate_content + and not certificate_path + and not (user and password) + and not client_secret + ): + raise M365ConfigCredentialsError( + file=os.path.basename(__file__), + message="You must provide a valid set of credentials. Please check your credentials and try again.", + ) @staticmethod def setup_region_config(region): @@ -378,6 +406,8 @@ class M365Provider(Provider): def setup_powershell( env_auth: bool = False, sp_env_auth: bool = False, + certificate_auth: bool = False, + certificate_path: str = None, m365_credentials: dict = {}, identity: M365IdentityInfo = None, init_modules: bool = False, @@ -402,6 +432,7 @@ class M365Provider(Provider): client_id=m365_credentials.get("client_id", ""), client_secret=m365_credentials.get("client_secret", ""), tenant_id=m365_credentials.get("tenant_id", ""), + certificate_content=m365_credentials.get("certificate_content", ""), tenant_domains=identity.tenant_domains, ) elif env_auth: @@ -440,10 +471,28 @@ class M365Provider(Provider): tenant_domains=identity.tenant_domains, ) + elif certificate_auth: + client_id = getenv("AZURE_CLIENT_ID") + tenant_id = getenv("AZURE_TENANT_ID") + if certificate_path: + with open(certificate_path, "rb") as cert_file: + # Encode the certificate content to base64 since PowerShell expects a base64 string + certificate_content = base64.b64encode(cert_file.read()) + else: + certificate_content = getenv("M365_CERTIFICATE_CONTENT") + credentials = M365Credentials( + client_id=client_id, + tenant_id=tenant_id, + certificate_content=certificate_content, + tenant_domains=identity.tenant_domains, + ) + if credentials: if identity and credentials.user: identity.user = credentials.user identity.identity_type = "Service Principal and User Credentials" + if identity and credentials.certificate_content: + identity.identity_type = "Service Principal with Certificate" test_session = M365PowerShell(credentials, identity) try: if init_modules: @@ -478,6 +527,10 @@ class M365Provider(Provider): report_lines.append( f"M365 User: {Fore.YELLOW}{self.credentials.user}{Style.RESET_ALL}" ) + elif self.credentials and self.credentials.certificate_content: + report_lines.append( + f"M365 Certificate Thumbprint: {Fore.YELLOW}{self._identity.certificate_thumbprint}{Style.RESET_ALL}" + ) report_title = ( f"{Style.BRIGHT}Using the M365 credentials below:{Style.RESET_ALL}" ) @@ -491,6 +544,8 @@ class M365Provider(Provider): sp_env_auth: bool, env_auth: bool, browser_auth: bool, + certificate_auth: bool, + certificate_path: str, tenant_id: str, m365_credentials: dict, region_config: M365RegionConfig, @@ -510,6 +565,8 @@ class M365Provider(Provider): - client_secret: The M365 client secret - user: The M365 user email - password: The M365 user password + - certificate_content: The M365 certificate content + - certificate_path: The path to the certificate file. - provider_id: The M365 provider ID (in this case the Tenant ID). region_config (M365RegionConfig): The region configuration object. @@ -530,16 +587,45 @@ class M365Provider(Provider): f"{environment_credentials_error.__class__.__name__}[{environment_credentials_error.__traceback__.tb_lineno}] -- {environment_credentials_error}" ) raise environment_credentials_error + elif certificate_auth: + try: + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=not certificate_path + ) + except M365EnvironmentVariableError as environment_variable_error: + logger.critical( + f"{environment_variable_error.__class__.__name__}[{environment_variable_error.__traceback__.tb_lineno}] -- {environment_variable_error}" + ) + raise environment_variable_error try: if m365_credentials: try: - credentials = ClientSecretCredential( - tenant_id=m365_credentials["tenant_id"], - client_id=m365_credentials["client_id"], - client_secret=m365_credentials["client_secret"], - user=m365_credentials["user"], - password=m365_credentials["password"], - ) + if m365_credentials["certificate_content"]: + credentials = CertificateCredential( + tenant_id=m365_credentials["tenant_id"], + client_id=m365_credentials["client_id"], + certificate_data=base64.b64decode( + m365_credentials["certificate_content"] + ), + ) + elif m365_credentials["certificate_path"]: + with open( + m365_credentials["certificate_path"], "rb" + ) as cert_file: + certificate_data = cert_file.read() + credentials = CertificateCredential( + tenant_id=m365_credentials["tenant_id"], + client_id=m365_credentials["client_id"], + certificate_data=certificate_data, + ) + else: + credentials = ClientSecretCredential( + tenant_id=m365_credentials["tenant_id"], + client_id=m365_credentials["client_id"], + client_secret=m365_credentials["client_secret"], + user=m365_credentials["user"], + password=m365_credentials["password"], + ) return credentials except ClientAuthenticationError as error: logger.error( @@ -562,13 +648,34 @@ class M365Provider(Provider): raise M365ConfigCredentialsError( file=os.path.basename(__file__), original_exception=error ) + elif certificate_auth: + try: + if certificate_path: + with open(certificate_path, "rb") as cert_file: + certificate_data = cert_file.read() + else: + certificate_data = base64.b64decode( + getenv("M365_CERTIFICATE_CONTENT") + ) + credentials = CertificateCredential( + tenant_id=getenv("AZURE_TENANT_ID"), + client_id=getenv("AZURE_CLIENT_ID"), + certificate_data=certificate_data, + ) + except ClientAuthenticationError as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}] -- {error}" + ) + raise M365ClientAuthenticationError( + file=os.path.basename(__file__), original_exception=error + ) else: # Since the authentication method to be used will come as True, we have to negate it since # DefaultAzureCredential sets just one authentication method, excluding the others try: credentials = DefaultAzureCredential( exclude_environment_credential=not ( - sp_env_auth or env_auth + sp_env_auth or env_auth or certificate_auth ), exclude_cli_credential=not az_cli_auth, # M365 Auth using Managed Identity is not supported @@ -633,6 +740,7 @@ class M365Provider(Provider): sp_env_auth: bool = False, env_auth: bool = False, browser_auth: bool = False, + certificate_auth: bool = False, tenant_id: str = None, region: str = "M365Global", raise_on_exception: bool = True, @@ -640,6 +748,8 @@ class M365Provider(Provider): client_secret: str = None, user: str = None, password: str = None, + certificate_content: str = None, + certificate_path: str = None, provider_id: str = None, ) -> Connection: """Test connection to M365 tenant and PowerShell modules. @@ -652,6 +762,7 @@ class M365Provider(Provider): sp_env_auth (bool): Flag indicating whether to use application authentication with environment variables. env_auth: (bool): Flag indicating whether to use application and PowerShell authentication with environment variables. browser_auth (bool): Flag indicating whether to use interactive browser authentication. + certificate_auth (bool): Flag indicating whether to use certificate authentication. tenant_id (str): The M365 Active Directory tenant ID. region (str): The M365 region. raise_on_exception (bool): Flag indicating whether to raise an exception if the connection fails. @@ -688,11 +799,14 @@ class M365Provider(Provider): sp_env_auth, env_auth, browser_auth, + certificate_auth, tenant_id, client_id, client_secret, user, password, + certificate_content, + certificate_path, ) region_config = M365Provider.setup_region_config(region) @@ -704,8 +818,6 @@ class M365Provider(Provider): tenant_id=tenant_id, client_id=client_id, client_secret=client_secret, - user=None, - password=None, ) else: m365_credentials = M365Provider.validate_static_credentials( @@ -715,6 +827,12 @@ class M365Provider(Provider): user=user, password=password, ) + elif tenant_id and client_id and certificate_content: + m365_credentials = M365Provider.validate_static_credentials( + tenant_id=tenant_id, + client_id=client_id, + certificate_content=certificate_content, + ) # Set up the M365 session session = M365Provider.setup_session( @@ -722,6 +840,8 @@ class M365Provider(Provider): sp_env_auth, env_auth, browser_auth, + certificate_auth, + certificate_path, tenant_id, m365_credentials, region_config, @@ -737,6 +857,7 @@ class M365Provider(Provider): env_auth, browser_auth, az_cli_auth, + certificate_auth, session, ) @@ -758,6 +879,8 @@ class M365Provider(Provider): M365Provider.setup_powershell( env_auth, sp_env_auth, + certificate_auth, + certificate_path, m365_credentials, identity, ) @@ -889,12 +1012,44 @@ class M365Provider(Provider): message=f"Missing environment variable {env_var} required to authenticate.", ) + @staticmethod + def check_certificate_creds_env_vars(check_certificate_content: bool): + """ + Checks the presence of required environment variables for service principal authentication against Azure. + + This method checks for the presence of the following environment variables: + - AZURE_CLIENT_ID: Azure client ID + - AZURE_TENANT_ID: Azure tenant ID + - M365_CERTIFICATE_CONTENT: Azure certificate content + + If any of the environment variables is missing, it logs a critical error and exits the program. + """ + logger.info( + "M365 provider: checking service principal environment variables ..." + ) + env_vars = [ + "AZURE_CLIENT_ID", + "AZURE_TENANT_ID", + ] + if check_certificate_content: + env_vars.append("M365_CERTIFICATE_CONTENT") + for env_var in env_vars: + if not getenv(env_var): + logger.critical( + f"M365 provider: Missing environment variable {env_var} needed to authenticate against M365." + ) + raise M365EnvironmentVariableError( + file=os.path.basename(__file__), + message=f"Missing environment variable {env_var} required to authenticate.", + ) + @staticmethod def setup_identity( sp_env_auth, env_auth, browser_auth, az_cli_auth, + certificate_auth, session, ): """ @@ -968,6 +1123,16 @@ class M365Provider(Provider): or session.credentials[0]._credential.client_id or "Unknown user id (Missing AAD permissions)" ) + elif certificate_auth: + identity.identity_type = "Service Principal with Certificate" + identity.identity_id = ( + getenv("AZURE_CLIENT_ID") + or session.credentials[0]._credential.client_id + or "Unknown user id (Missing AAD permissions)" + ) + identity.certificate_thumbprint = session._client_credential.get( + "thumbprint", "Unknown certificate thumbprint" + ) elif browser_auth or az_cli_auth: identity.identity_type = "User" try: @@ -987,8 +1152,14 @@ class M365Provider(Provider): ) else: # Static Credentials - identity.identity_type = "Service Principal" identity.identity_id = session._client_id + if isinstance(session, CertificateCredential): + identity.identity_type = "Service Principal with Certificate" + identity.certificate_thumbprint = session._client_credential.get( + "thumbprint", "Unknown certificate thumbprint" + ) + else: + identity.identity_type = "Service Principal" # Retrieve tenant id from the client client = GraphServiceClient(credentials=session) @@ -1005,6 +1176,8 @@ class M365Provider(Provider): client_secret: str = None, user: str = None, password: str = None, + certificate_content: str = None, + certificate_path: str = None, ) -> dict: """ Validates the static credentials for the M365 provider. @@ -1015,6 +1188,8 @@ class M365Provider(Provider): client_secret (str): The M365 client secret. user (str): The M365 user email. password (str): The M365 user password. + certificate_content (str): The M365 Certificate Content. + certificate_path (str): The path to the certificate file. Raises: M365NotValidTenantIdError: If the provided M365 Tenant ID is not valid. @@ -1045,21 +1220,47 @@ class M365Provider(Provider): message="The provided Client ID is not valid.", ) - # Validate the Client Secret - if not client_secret: + if not certificate_content and not certificate_path and not client_secret: raise M365NotValidClientSecretError( file=os.path.basename(__file__), - message="The provided Client Secret is not valid.", + message="You must provide a client secret, certificate content or certificate path. Please check your credentials and try again.", ) + if certificate_content: + try: + # Validate that certificate content can be properly decoded from base64 + base64.b64decode(certificate_content) + except Exception as e: + raise M365NotValidCertificateContentError( + file=os.path.basename(__file__), + message=f"The provided certificate content is not valid base64 encoded data: {str(e)}", + ) + if certificate_path: + try: + with open(certificate_path, "rb") as cert_file: + certificate_content = cert_file.read() + except Exception as e: + raise M365NotValidCertificatePathError( + file=os.path.basename(__file__), + message=f"The provided certificate path is not valid: {str(e)}", + ) + try: - M365Provider.verify_client(tenant_id, client_id, client_secret) + M365Provider.verify_client( + tenant_id, + client_id, + client_secret, + certificate_content, + certificate_path, + ) return { "tenant_id": tenant_id, "client_id": client_id, "client_secret": client_secret, "user": user, "password": password, + "certificate_content": certificate_content, + "certificate_path": certificate_path, } except M365NotValidTenantIdError as tenant_id_error: logger.error( @@ -1087,7 +1288,9 @@ class M365Provider(Provider): ) @staticmethod - def verify_client(tenant_id, client_id, client_secret) -> None: + def verify_client( + tenant_id, client_id, client_secret, certificate_content, certificate_path + ) -> None: """ Verifies the M365 client credentials using the specified tenant ID, client ID, and client secret. @@ -1095,52 +1298,106 @@ class M365Provider(Provider): tenant_id (str): The M365 Active Directory tenant ID. client_id (str): The M365 client ID. client_secret (str): The M365 client secret. + certificate_content (str): The M365 certificate content. + certificate_path (str): The path to the certificate file. Raises: M365NotValidTenantIdError: If the provided M365 Tenant ID is not valid. M365NotValidClientIdError: If the provided M365 Client ID is not valid. M365NotValidClientSecretError: If the provided M365 Client Secret is not valid. + M365NotValidCertificateContentError: If the provided M365 Certificate Content is not valid. + M365NotValidCertificatePathError: If the provided M365 Certificate Path is not valid. Returns: None """ authority = f"https://login.microsoftonline.com/{tenant_id}" try: - # Create a ConfidentialClientApplication instance - app = ConfidentialClientApplication( - client_id=client_id, - client_credential=client_secret, - authority=authority, - ) + if client_secret: + # Create a ConfidentialClientApplication instance + app = ConfidentialClientApplication( + client_id=client_id, + client_credential=client_secret, + authority=authority, + ) + # Attempt to acquire a token + result = app.acquire_token_for_client( + scopes=["https://graph.microsoft.com/.default"] + ) - # Attempt to acquire a token - result = app.acquire_token_for_client( - scopes=["https://graph.microsoft.com/.default"] - ) + # Check if token acquisition was successful + if "access_token" not in result: + # Handle specific errors based on the MSAL response + error_description = result.get("error_description", "") + if f"Tenant '{tenant_id}'" in error_description: + raise M365NotValidTenantIdError( + file=os.path.basename(__file__), + message="The provided Tenant ID is not valid for the specified Client ID and Client Secret.", + ) + if ( + f"Application with identifier '{client_id}'" + in error_description + ): + raise M365NotValidClientIdError( + file=os.path.basename(__file__), + message="The provided Client ID is not valid for the specified Tenant ID and Client Secret.", + ) + if "Invalid client secret provided" in error_description: + raise M365NotValidClientSecretError( + file=os.path.basename(__file__), + message="The provided Client Secret is not valid for the specified Tenant ID and Client ID.", + ) + elif certificate_content: + credential = CertificateCredential( + client_id=client_id, + tenant_id=tenant_id, + certificate_data=base64.b64decode(certificate_content), + ) + client = GraphServiceClient(credentials=credential) - # Check if token acquisition was successful - if "access_token" not in result: - # Handle specific errors based on the MSAL response - error_description = result.get("error_description", "") - if f"Tenant '{tenant_id}'" in error_description: - raise M365NotValidTenantIdError( + # Verify that the certificate is valid + async def verify_certificate(): + result = await client.domains.get() + return result.value + + result = asyncio.get_event_loop().run_until_complete( + verify_certificate() + ) + if not result: + raise M365NotValidCertificateContentError( file=os.path.basename(__file__), - message="The provided Tenant ID is not valid for the specified Client ID and Client Secret.", + message="The provided certificate content is not valid.", ) - if f"Application with identifier '{client_id}'" in error_description: - raise M365NotValidClientIdError( + elif certificate_path: + with open(certificate_path, "rb") as cert_file: + certificate_content = cert_file.read() + credential = CertificateCredential( + client_id=client_id, + tenant_id=tenant_id, + certificate_data=certificate_content, + ) + client = GraphServiceClient(credentials=credential) + + # Verify that the certificate is valid + async def verify_certificate(): + result = await client.domains.get() + return result.value + + result = asyncio.get_event_loop().run_until_complete( + verify_certificate() + ) + if not result: + raise M365NotValidCertificatePathError( file=os.path.basename(__file__), - message="The provided Client ID is not valid for the specified Tenant ID and Client Secret.", - ) - if "Invalid client secret provided" in error_description: - raise M365NotValidClientSecretError( - file=os.path.basename(__file__), - message="The provided Client Secret is not valid for the specified Tenant ID and Client ID.", + message="The provided certificate is not valid.", ) + except ( M365NotValidTenantIdError, M365NotValidClientIdError, M365NotValidClientSecretError, + M365NotValidCertificateContentError, + M365NotValidCertificatePathError, ) as m365_error: # M365 specific errors already raised raise RuntimeError(f"{m365_error}") diff --git a/prowler/providers/m365/models.py b/prowler/providers/m365/models.py index ff2cec2fd5..3459b31688 100644 --- a/prowler/providers/m365/models.py +++ b/prowler/providers/m365/models.py @@ -11,6 +11,7 @@ class M365IdentityInfo(BaseModel): identity_type: str = "" tenant_id: str = "" tenant_domain: str = "Unknown tenant domain (missing Entra permissions)" + certificate_thumbprint: str = "" tenant_domains: list[str] = [] location: str = "" user: str = None @@ -28,9 +29,10 @@ class M365Credentials(BaseModel): passwd: Optional[str] = None encrypted_passwd: Optional[str] = None client_id: str = "" - client_secret: str = "" + client_secret: Optional[str] = None tenant_id: str = "" tenant_domains: list[str] = [] + certificate_content: Optional[str] = None class M365OutputOptions(ProviderOutputOptions): diff --git a/tests/providers/m365/lib/arguments/m365_arguments_test.py b/tests/providers/m365/lib/arguments/m365_arguments_test.py new file mode 100644 index 0000000000..220ff40f8f --- /dev/null +++ b/tests/providers/m365/lib/arguments/m365_arguments_test.py @@ -0,0 +1,641 @@ +import argparse +from unittest.mock import MagicMock + +from prowler.providers.m365.lib.arguments import arguments + + +class TestM365Arguments: + def setup_method(self): + """Setup mock ArgumentParser for testing""" + self.mock_parser = MagicMock() + self.mock_subparsers = MagicMock() + self.mock_m365_parser = MagicMock() + self.mock_auth_group = MagicMock() + self.mock_auth_modes_group = MagicMock() + self.mock_regions_group = MagicMock() + + # Setup the mock chain + self.mock_parser.add_subparsers.return_value = self.mock_subparsers + self.mock_subparsers.add_parser.return_value = self.mock_m365_parser + self.mock_m365_parser.add_argument_group.side_effect = [ + self.mock_auth_group, + self.mock_regions_group, + ] + self.mock_auth_group.add_mutually_exclusive_group.return_value = ( + self.mock_auth_modes_group + ) + + def test_init_parser_creates_subparser(self): + """Test that init_parser creates the M365 subparser correctly""" + # Create a mock object that has the necessary attributes + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + # Call init_parser + arguments.init_parser(mock_m365_args) + + # Verify subparser was created + self.mock_subparsers.add_parser.assert_called_once_with( + "m365", + parents=[mock_m365_args.common_providers_parser], + help="M365 Provider", + ) + + def test_init_parser_creates_argument_groups(self): + """Test that init_parser creates the correct argument groups""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Verify argument groups were created + assert self.mock_m365_parser.add_argument_group.call_count == 2 + calls = self.mock_m365_parser.add_argument_group.call_args_list + assert calls[0][0][0] == "Authentication Modes" + assert calls[1][0][0] == "Regions" + + def test_init_parser_creates_mutually_exclusive_auth_group(self): + """Test that init_parser creates mutually exclusive authentication group""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Verify mutually exclusive group was created for authentication modes + self.mock_auth_group.add_mutually_exclusive_group.assert_called_once() + + def test_init_parser_adds_authentication_arguments(self): + """Test that init_parser adds all authentication arguments""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Verify authentication arguments were added to the mutually exclusive group + assert self.mock_auth_modes_group.add_argument.call_count == 5 + + # Check that all authentication arguments are present + calls = self.mock_auth_modes_group.add_argument.call_args_list + auth_args = [call[0][0] for call in calls] + + assert "--az-cli-auth" in auth_args + assert "--env-auth" in auth_args + assert "--sp-env-auth" in auth_args + assert "--browser-auth" in auth_args + assert "--certificate-auth" in auth_args + + def test_init_parser_adds_non_exclusive_arguments(self): + """Test that init_parser adds non-exclusive arguments directly to parser""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Verify non-exclusive arguments were added to main parser + assert self.mock_m365_parser.add_argument.call_count == 3 + + # Check that non-exclusive arguments are present + calls = self.mock_m365_parser.add_argument.call_args_list + non_exclusive_args = [call[0][0] for call in calls] + + assert "--tenant-id" in non_exclusive_args + assert "--init-modules" in non_exclusive_args + assert "--certificate-path" in non_exclusive_args + + def test_init_parser_adds_region_arguments(self): + """Test that init_parser adds region arguments""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Verify region arguments were added to regions group + assert self.mock_regions_group.add_argument.call_count == 1 + + # Check that region argument is present + calls = self.mock_regions_group.add_argument.call_args_list + region_args = [call[0][0] for call in calls] + + assert "--region" in region_args + + def test_az_cli_auth_argument_configuration(self): + """Test that az-cli-auth argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the az-cli-auth argument call + calls = self.mock_auth_modes_group.add_argument.call_args_list + az_cli_call = None + for call in calls: + if call[0][0] == "--az-cli-auth": + az_cli_call = call + break + + assert az_cli_call is not None + + # Check argument configuration + kwargs = az_cli_call[1] + assert kwargs["action"] == "store_true" + assert "Azure CLI authentication" in kwargs["help"] + + def test_env_auth_argument_configuration(self): + """Test that env-auth argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the env-auth argument call + calls = self.mock_auth_modes_group.add_argument.call_args_list + env_auth_call = None + for call in calls: + if call[0][0] == "--env-auth": + env_auth_call = call + break + + assert env_auth_call is not None + + # Check argument configuration + kwargs = env_auth_call[1] + assert kwargs["action"] == "store_true" + assert "User and Password environment variables" in kwargs["help"] + + def test_sp_env_auth_argument_configuration(self): + """Test that sp-env-auth argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the sp-env-auth argument call + calls = self.mock_auth_modes_group.add_argument.call_args_list + sp_env_call = None + for call in calls: + if call[0][0] == "--sp-env-auth": + sp_env_call = call + break + + assert sp_env_call is not None + + # Check argument configuration + kwargs = sp_env_call[1] + assert kwargs["action"] == "store_true" + assert "Azure Service Principal environment variables" in kwargs["help"] + + def test_browser_auth_argument_configuration(self): + """Test that browser-auth argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the browser-auth argument call + calls = self.mock_auth_modes_group.add_argument.call_args_list + browser_auth_call = None + for call in calls: + if call[0][0] == "--browser-auth": + browser_auth_call = call + break + + assert browser_auth_call is not None + + # Check argument configuration + kwargs = browser_auth_call[1] + assert kwargs["action"] == "store_true" + assert "Azure interactive browser authentication" in kwargs["help"] + + def test_certificate_auth_argument_configuration(self): + """Test that certificate-auth argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the certificate-auth argument call + calls = self.mock_auth_modes_group.add_argument.call_args_list + cert_auth_call = None + for call in calls: + if call[0][0] == "--certificate-auth": + cert_auth_call = call + break + + assert cert_auth_call is not None + + # Check argument configuration + kwargs = cert_auth_call[1] + assert kwargs["action"] == "store_true" + assert "Certificate authentication" in kwargs["help"] + + def test_tenant_id_argument_configuration(self): + """Test that tenant-id argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the tenant-id argument call + calls = self.mock_m365_parser.add_argument.call_args_list + tenant_id_call = None + for call in calls: + if call[0][0] == "--tenant-id": + tenant_id_call = call + break + + assert tenant_id_call is not None + + # Check argument configuration + kwargs = tenant_id_call[1] + assert kwargs["nargs"] == "?" + assert kwargs["default"] is None + assert "Microsoft 365 Tenant ID" in kwargs["help"] + assert "--browser-auth" in kwargs["help"] + + def test_init_modules_argument_configuration(self): + """Test that init-modules argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the init-modules argument call + calls = self.mock_m365_parser.add_argument.call_args_list + init_modules_call = None + for call in calls: + if call[0][0] == "--init-modules": + init_modules_call = call + break + + assert init_modules_call is not None + + # Check argument configuration + kwargs = init_modules_call[1] + assert kwargs["action"] == "store_true" + assert "Initialize Microsoft 365 PowerShell modules" in kwargs["help"] + + def test_region_argument_configuration(self): + """Test that region argument is configured correctly""" + mock_m365_args = MagicMock() + mock_m365_args.subparsers = self.mock_subparsers + mock_m365_args.common_providers_parser = MagicMock() + + arguments.init_parser(mock_m365_args) + + # Find the region argument call + calls = self.mock_regions_group.add_argument.call_args_list + region_call = None + for call in calls: + if call[0][0] == "--region": + region_call = call + break + + assert region_call is not None + + # Check argument configuration + kwargs = region_call[1] + assert kwargs["nargs"] == "?" + assert kwargs["default"] == "M365Global" + assert kwargs["choices"] == [ + "M365Global", + "M365GlobalChina", + "M365USGovernment", + ] + assert "Microsoft 365 region" in kwargs["help"] + assert "M365Global" in kwargs["help"] + + +class TestM365ArgumentsIntegration: + def test_real_argument_parsing_az_cli_auth(self): + """Test parsing arguments with Azure CLI authentication""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + # Create a mock object that mimics the structure used by the init_parser function + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with Azure CLI auth + args = parser.parse_args(["m365", "--az-cli-auth"]) + + assert args.az_cli_auth is True + assert args.env_auth is False + assert args.sp_env_auth is False + assert args.browser_auth is False + assert args.certificate_auth is False + + def test_real_argument_parsing_env_auth(self): + """Test parsing arguments with environment authentication""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with environment auth + args = parser.parse_args(["m365", "--env-auth"]) + + assert args.az_cli_auth is False + assert args.env_auth is True + assert args.sp_env_auth is False + assert args.browser_auth is False + assert args.certificate_auth is False + + def test_real_argument_parsing_sp_env_auth(self): + """Test parsing arguments with service principal environment authentication""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with service principal environment auth + args = parser.parse_args(["m365", "--sp-env-auth"]) + + assert args.az_cli_auth is False + assert args.env_auth is False + assert args.sp_env_auth is True + assert args.browser_auth is False + assert args.certificate_auth is False + + def test_real_argument_parsing_browser_auth_with_tenant_id(self): + """Test parsing arguments with browser authentication and tenant ID""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with browser auth and tenant ID + args = parser.parse_args( + [ + "m365", + "--browser-auth", + "--tenant-id", + "12345678-1234-5678-abcd-123456789012", + ] + ) + + assert args.az_cli_auth is False + assert args.env_auth is False + assert args.sp_env_auth is False + assert args.browser_auth is True + assert args.certificate_auth is False + assert args.tenant_id == "12345678-1234-5678-abcd-123456789012" + + def test_real_argument_parsing_certificate_auth(self): + """Test parsing arguments with certificate authentication""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with certificate auth + args = parser.parse_args(["m365", "--certificate-auth"]) + + assert args.az_cli_auth is False + assert args.env_auth is False + assert args.sp_env_auth is False + assert args.browser_auth is False + assert args.certificate_auth is True + + def test_real_argument_parsing_with_init_modules(self): + """Test parsing arguments with init modules flag""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with init modules + args = parser.parse_args(["m365", "--az-cli-auth", "--init-modules"]) + + assert args.az_cli_auth is True + assert args.init_modules is True + + def test_real_argument_parsing_with_different_regions(self): + """Test parsing arguments with different region options""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Test M365Global (default) + args = parser.parse_args(["m365", "--az-cli-auth"]) + assert args.region == "M365Global" + + # Test M365GlobalChina + args = parser.parse_args( + ["m365", "--az-cli-auth", "--region", "M365GlobalChina"] + ) + assert args.region == "M365GlobalChina" + + # Test M365USGovernment + args = parser.parse_args( + ["m365", "--az-cli-auth", "--region", "M365USGovernment"] + ) + assert args.region == "M365USGovernment" + + def test_real_argument_parsing_no_authentication_defaults(self): + """Test parsing arguments without any authentication flags (should have defaults)""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments without explicit auth (defaults should apply) + args = parser.parse_args(["m365"]) + + assert args.az_cli_auth is False + assert args.env_auth is False + assert args.sp_env_auth is False + assert args.browser_auth is False + assert args.certificate_auth is False + assert args.tenant_id is None + assert args.init_modules is False + assert args.region == "M365Global" + + def test_real_argument_parsing_complete_configuration(self): + """Test parsing arguments with all non-exclusive options""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with complete configuration + args = parser.parse_args( + [ + "m365", + "--browser-auth", + "--tenant-id", + "12345678-1234-5678-abcd-123456789012", + "--init-modules", + "--region", + "M365USGovernment", + ] + ) + + assert args.browser_auth is True + assert args.tenant_id == "12345678-1234-5678-abcd-123456789012" + assert args.init_modules is True + assert args.region == "M365USGovernment" + + def test_mutually_exclusive_authentication_enforcement(self): + """Test that authentication methods are mutually exclusive""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # This should raise SystemExit due to mutually exclusive group + try: + parser.parse_args(["m365", "--az-cli-auth", "--env-auth"]) + assert False, "Expected SystemExit due to mutually exclusive arguments" + except SystemExit: + # This is expected + pass + + def test_tenant_id_without_arguments(self): + """Test that tenant-id can be specified without an argument (optional value)""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with tenant-id but no value (should be None due to nargs="?") + args = parser.parse_args(["m365", "--az-cli-auth", "--tenant-id"]) + + assert args.tenant_id is None + + def test_certificate_path_argument_configuration(self): + """Test that certificate_path argument is properly configured""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with certificate-path + args = parser.parse_args( + ["m365", "--certificate-auth", "--certificate-path", "/path/to/cert.pem"] + ) + + assert args.certificate_auth is True + assert args.certificate_path == "/path/to/cert.pem" + + def test_certificate_path_without_value(self): + """Test certificate_path argument without value (should be None due to nargs='?')""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse arguments with certificate-path but no value + args = parser.parse_args(["m365", "--certificate-auth", "--certificate-path"]) + + assert args.certificate_auth is True + assert args.certificate_path is None + + def test_certificate_auth_with_certificate_path_integration(self): + """Test certificate authentication with certificate path integration""" + parser = argparse.ArgumentParser() + subparsers = parser.add_subparsers() + common_parser = argparse.ArgumentParser(add_help=False) + + mock_m365_args = MagicMock() + mock_m365_args.subparsers = subparsers + mock_m365_args.common_providers_parser = common_parser + + arguments.init_parser(mock_m365_args) + + # Parse complete certificate authentication arguments + args = parser.parse_args( + [ + "m365", + "--certificate-auth", + "--certificate-path", + "/home/user/cert.pem", + "--tenant-id", + "12345678-1234-1234-1234-123456789012", + ] + ) + + assert args.certificate_auth is True + assert args.certificate_path == "/home/user/cert.pem" + assert args.tenant_id == "12345678-1234-1234-1234-123456789012" + assert args.az_cli_auth is False + assert args.env_auth is False + assert args.sp_env_auth is False + assert args.browser_auth is False diff --git a/tests/providers/m365/lib/powershell/m365_powershell_test.py b/tests/providers/m365/lib/powershell/m365_powershell_test.py index 2e6a34a032..bd45956de0 100644 --- a/tests/providers/m365/lib/powershell/m365_powershell_test.py +++ b/tests/providers/m365/lib/powershell/m365_powershell_test.py @@ -1,9 +1,11 @@ +import base64 from unittest.mock import MagicMock, call, patch import pytest from prowler.lib.powershell.powershell import PowerShellSession from prowler.providers.m365.exceptions.exceptions import ( + M365CertificateCreationError, M365GraphConnectionError, M365UserCredentialsError, M365UserNotBelongingToTenantError, @@ -112,7 +114,7 @@ class Testm365PowerShell: session.close() @patch("subprocess.Popen") - def test_test_credentials(self, mock_popen): + def test_test_credentials_exchange_success(self, mock_popen): mock_process = MagicMock() mock_popen.return_value = mock_process @@ -131,16 +133,20 @@ class Testm365PowerShell: tenant_domain="contoso.onmicrosoft.com", tenant_domains=["contoso.onmicrosoft.com"], location="test_location", + user="test@contoso.onmicrosoft.com", ) session = M365PowerShell(credentials, identity) # Mock encrypt_password to return a known value session.encrypt_password = MagicMock(return_value="encrypted_password") - # Mock execute to simulate successful Connect-ExchangeOnline - session.execute = MagicMock( - return_value="Connected successfully https://aka.ms/exov3-module" - ) + # Mock execute to simulate successful Exchange connection + def mock_execute_side_effect(command): + if "Connect-ExchangeOnline" in command: + return "Connected successfully https://aka.ms/exov3-module" + return "" + + session.execute = MagicMock(side_effect=mock_execute_side_effect) # Execute the test result = session.test_credentials(credentials) @@ -153,42 +159,110 @@ class Testm365PowerShell: session.execute.assert_any_call( f'$credential = New-Object System.Management.Automation.PSCredential("{session.sanitize(credentials.user)}", $securePassword)' ) + # Exchange connection should be tested session.execute.assert_any_call( "Connect-ExchangeOnline -Credential $credential" ) + # Verify Teams connection was NOT called (since Exchange succeeded) + teams_calls = [ + call + for call in session.execute.call_args_list + if "Connect-MicrosoftTeams" in str(call) + ] + assert ( + len(teams_calls) == 0 + ), "Teams connection should not be called when Exchange succeeds" + + session.close() + + @patch("subprocess.Popen") + def test_test_credentials_exchange_fail_teams_success(self, mock_popen): + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials( + user="test@contoso.onmicrosoft.com", + passwd="test_password", + encrypted_passwd="test_encrypted_password", + client_id="test_client_id", + client_secret="test_client_secret", + tenant_id="test_tenant_id", + ) + identity = M365IdentityInfo( + identity_id="test_id", + identity_type="User", + tenant_id="test_tenant", + tenant_domain="contoso.onmicrosoft.com", + tenant_domains=["contoso.onmicrosoft.com"], + location="test_location", + user="test@contoso.onmicrosoft.com", + ) + session = M365PowerShell(credentials, identity) + + # Mock encrypt_password to return a known value + session.encrypt_password = MagicMock(return_value="encrypted_password") + + # Mock execute to simulate Exchange fail and Teams success + def mock_execute_side_effect(command): + if "Connect-ExchangeOnline" in command: + return ( + "Connection failed" # No "https://aka.ms/exov3-module" in response + ) + elif "Connect-MicrosoftTeams" in command: + return "Connected successfully test@contoso.onmicrosoft.com" + return "" + + session.execute = MagicMock(side_effect=mock_execute_side_effect) + + # Execute the test + result = session.test_credentials(credentials) + assert result is True + + # Verify execute was called with the correct commands + session.execute.assert_any_call( + f'$securePassword = "{credentials.encrypted_passwd}" | ConvertTo-SecureString' + ) + session.execute.assert_any_call( + f'$credential = New-Object System.Management.Automation.PSCredential("{session.sanitize(credentials.user)}", $securePassword)' + ) + # Both Exchange and Teams connections should be tested + session.execute.assert_any_call( + "Connect-ExchangeOnline -Credential $credential" + ) + session.execute.assert_any_call( + "Connect-MicrosoftTeams -Credential $credential" + ) + session.close() @patch("subprocess.Popen") def test_test_credentials_application_auth(self, mock_popen): mock_process = MagicMock() mock_popen.return_value = mock_process - with patch( - "prowler.providers.m365.lib.powershell.m365_powershell.M365Credentials", - autospec=True, - ) as mock_creds: - credentials = mock_creds.return_value - credentials.user = "" - credentials.passwd = "" - credentials.encrypted_passwd = "" - credentials.client_id = "test_client_id" - credentials.client_secret = "test_client_secret" - credentials.tenant_id = "test_tenant_id" - identity = M365IdentityInfo( - identity_id="test_id", - identity_type="Application", - tenant_id="test_tenant", - tenant_domain="contoso.onmicrosoft.com", - tenant_domains=["contoso.onmicrosoft.com"], - location="test_location", - ) - session = M365PowerShell(credentials, identity) - session.execute = MagicMock(return_value="sometoken") + credentials = M365Credentials( + user="", + passwd="", + encrypted_passwd="", + client_id="test_client_id", + client_secret="test_client_secret", + tenant_id="test_tenant_id", + ) + identity = M365IdentityInfo( + identity_id="test_id", + identity_type="Application", + tenant_id="test_tenant", + tenant_domain="contoso.onmicrosoft.com", + tenant_domains=["contoso.onmicrosoft.com"], + location="test_location", + ) + session = M365PowerShell(credentials, identity) + session.execute = MagicMock(return_value="sometoken") - result = session.test_credentials(credentials) - assert result is True - session.execute.assert_any_call("Write-Output $graphToken") - session.close() + result = session.test_credentials(credentials) + assert result is True + session.execute.assert_any_call("Write-Output $graphToken") + session.close() @patch("subprocess.Popen") @patch("msal.ConfidentialClientApplication") @@ -748,7 +822,8 @@ class Testm365PowerShell: assert result is True # Verify all expected PowerShell commands were called - assert session.execute.call_count == 3 + # 4 calls: teamstokenBody, teamsToken, Write-Output $teamsToken, Connect-MicrosoftTeams + assert session.execute.call_count == 4 mock_decode_jwt.assert_called_once_with("valid_teams_token") session.close() @@ -849,7 +924,8 @@ class Testm365PowerShell: assert result is True # Verify all expected PowerShell commands were called - assert session.execute.call_count == 3 + # 4 calls: SecureSecret, exchangeToken, Write-Output $exchangeToken, Connect-ExchangeOnline + assert session.execute.call_count == 4 mock_decode_msal_token.assert_called_once_with("valid_exchange_token") session.close() @@ -970,3 +1046,623 @@ class Testm365PowerShell: del sys.modules["win32crypt"] session.close() + + @patch("subprocess.Popen") + def test_clean_certificate_content(self, mock_popen): + """Test clean_certificate_content method with various certificate content formats""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo() + session = M365PowerShell(credentials, identity) + + # Test with clean base64 content + clean_cert = "MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV" + result = session.clean_certificate_content(clean_cert) + assert result == clean_cert + + # Test with newlines + cert_with_newlines = "MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\nBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldA==" + expected = "MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldA==" + result = session.clean_certificate_content(cert_with_newlines) + assert result == expected + + # Test with carriage returns + cert_with_cr = "MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\rBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldA==" + result = session.clean_certificate_content(cert_with_cr) + assert result == expected + + # Test with spaces + cert_with_spaces = "MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldA==" + result = session.clean_certificate_content(cert_with_spaces) + assert result == expected + + # Test with combination of all whitespace types + cert_mixed = "MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n\r BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldA==" + result = session.clean_certificate_content(cert_mixed) + assert result == expected + + # Test with leading/trailing whitespace + cert_with_whitespace = " MIIDXTCCAkWgAwIBAgIJAJc1HiIAZAiIMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldA== " + result = session.clean_certificate_content(cert_with_whitespace) + assert result == expected + + session.close() + + @patch("subprocess.Popen") + def test_init_credential_certificate_auth(self, mock_popen): + """Test init_credential method with certificate authentication""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + credentials = M365Credentials( + client_id="test_client_id", + tenant_id="test_tenant_id", + certificate_content=certificate_content, + tenant_domains=["example.com"], + ) + identity = M365IdentityInfo(tenant_domains=["example.com"]) + + # Create session without calling init_credential + with patch.object(M365PowerShell, "init_credential"): + session = M365PowerShell(credentials, identity) + + # Mock the execute method + execute_calls = [] + + def mock_execute(command): + execute_calls.append(command) + if ( + "New-Object System.Security.Cryptography.X509Certificates.X509Certificate2" + in command + ): + return "" # No error + return "" + + session.execute = MagicMock(side_effect=mock_execute) + session.sanitize = MagicMock(side_effect=lambda x: x) + session.clean_certificate_content = MagicMock(return_value=certificate_content) + + # Now call init_credential + session.init_credential(credentials) + + # Verify clean_certificate_content was called + session.clean_certificate_content.assert_called_once_with(certificate_content) + + # Verify sanitize was called for client_id and tenant_id + session.sanitize.assert_any_call(credentials.client_id) + session.sanitize.assert_any_call(credentials.tenant_id) + + # Verify execute was called with correct commands + session.execute.assert_any_call( + f'$certBytes = [Convert]::FromBase64String("{certificate_content}")' + ) + session.execute.assert_any_call( + "$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(,$certBytes)" + ) + session.execute.assert_any_call(f'$clientID = "{credentials.client_id}"') + session.execute.assert_any_call(f'$tenantID = "{credentials.tenant_id}"') + session.execute.assert_any_call( + f'$tenantDomain = "{credentials.tenant_domains[0]}"' + ) + + session.close() + + @patch("subprocess.Popen") + def test_init_credential_certificate_auth_creation_error(self, mock_popen): + """Test init_credential method with certificate authentication when certificate creation fails""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + certificate_content = base64.b64encode(b"invalid_certificate").decode("utf-8") + credentials = M365Credentials( + client_id="test_client_id", + tenant_id="test_tenant_id", + certificate_content=certificate_content, + tenant_domains=["example.com"], + ) + identity = M365IdentityInfo(tenant_domains=["example.com"]) + + # Create session without calling init_credential + with patch.object(M365PowerShell, "init_credential"): + session = M365PowerShell(credentials, identity) + + # Mock the execute method to simulate certificate creation error + def mock_execute(command): + if ( + "New-Object System.Security.Cryptography.X509Certificates.X509Certificate2" + in command + ): + return "Certificate creation failed: Invalid certificate format" + return "" + + session.execute = MagicMock(side_effect=mock_execute) + session.sanitize = MagicMock(side_effect=lambda x: x) + session.clean_certificate_content = MagicMock(return_value=certificate_content) + + with pytest.raises(M365CertificateCreationError) as exc_info: + session.init_credential(credentials) + + # The actual error message format from the exception + assert "Failed to create X.509 certificate object" in str(exc_info.value) + + session.close() + + @patch("subprocess.Popen") + def test_test_exchange_certificate_connection_success(self, mock_popen): + """Test test_exchange_certificate_connection method with successful connection""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo() + session = M365PowerShell(credentials, identity) + + # Mock successful Exchange connection + session.execute = MagicMock( + return_value="Connected successfully https://aka.ms/exov3-module" + ) + + result = session.test_exchange_certificate_connection() + assert result is True + + session.execute.assert_called_once_with( + "Connect-ExchangeOnline -Certificate $certificate -AppId $clientID -Organization $tenantDomain" + ) + + session.close() + + @patch("subprocess.Popen") + def test_test_exchange_certificate_connection_failure(self, mock_popen): + """Test test_exchange_certificate_connection method with failed connection""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo() + session = M365PowerShell(credentials, identity) + + # Mock failed Exchange connection + session.execute = MagicMock( + return_value="Connection failed: Authentication error" + ) + + result = session.test_exchange_certificate_connection() + assert result is False + + session.execute.assert_called_once_with( + "Connect-ExchangeOnline -Certificate $certificate -AppId $clientID -Organization $tenantDomain" + ) + + session.close() + + @patch("subprocess.Popen") + def test_test_teams_certificate_connection_success(self, mock_popen): + """Test test_teams_certificate_connection method with successful connection""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo(identity_id="test_identity_id") + + # Create session without calling init_credential + with patch.object(M365PowerShell, "init_credential"): + session = M365PowerShell(credentials, identity) + + # Mock successful Teams connection - the method returns bool + def mock_execute_side_effect(command): + if "Connect-MicrosoftTeams" in command: + # Return result that contains the identity_id for success + return "Connected successfully test_identity_id" + return "" + + session.execute = MagicMock(side_effect=mock_execute_side_effect) + + result = session.test_teams_certificate_connection() + assert result is True + + session.execute.assert_called_once_with( + "Connect-MicrosoftTeams -Certificate $certificate -ApplicationId $clientID -TenantId $tenantID" + ) + + session.close() + + @patch("subprocess.Popen") + def test_test_teams_certificate_connection_failure(self, mock_popen): + """Test test_teams_certificate_connection method with failed connection""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo() + session = M365PowerShell(credentials, identity) + + # Mock failed Teams connection + def mock_execute_side_effect(command, json_parse=False): + if "Connect-MicrosoftTeams" in command: + raise Exception("Connection failed: Authentication error") + return "" + + session.execute = MagicMock(side_effect=mock_execute_side_effect) + + # Should raise exception on connection failure + with pytest.raises(Exception) as exc_info: + session.test_teams_certificate_connection() + + assert "Connection failed: Authentication error" in str(exc_info.value) + + session.close() + + @patch("subprocess.Popen") + def test_test_credentials_certificate_auth_success(self, mock_popen): + """Test test_credentials method with certificate authentication - successful""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + credentials = M365Credentials( + client_id="test_client_id", certificate_content=certificate_content + ) + identity = M365IdentityInfo() + + # Create session without calling init_credential + with patch.object(M365PowerShell, "init_credential"): + session = M365PowerShell(credentials, identity) + + # Mock successful certificate connections + # Note: The actual implementation uses "or" so if teams succeeds, exchange won't be called + session.test_teams_certificate_connection = MagicMock(return_value=True) + session.test_exchange_certificate_connection = MagicMock(return_value=True) + + result = session.test_credentials(credentials) + assert result is True + + session.test_teams_certificate_connection.assert_called_once() + # Exchange connection should NOT be called if teams connection succeeds (due to "or" logic) + session.test_exchange_certificate_connection.assert_not_called() + + session.close() + + @patch("subprocess.Popen") + def test_test_credentials_certificate_auth_failure(self, mock_popen): + """Test test_credentials method with certificate authentication - failure""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + credentials = M365Credentials( + client_id="test_client_id", certificate_content=certificate_content + ) + identity = M365IdentityInfo() + + # Create session without calling init_credential + with patch.object(M365PowerShell, "init_credential"): + session = M365PowerShell(credentials, identity) + + # Mock failed certificate connections - teams fails, so exchange is tried + session.test_teams_certificate_connection = MagicMock(return_value=False) + session.test_exchange_certificate_connection = MagicMock(return_value=False) + + result = session.test_credentials(credentials) + assert result is True # Method always returns True after the try block + + session.close() + + @patch("subprocess.Popen") + def test_connect_microsoft_teams_certificate_auth(self, mock_popen): + """Test connect_microsoft_teams method with certificate authentication""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo() + session = M365PowerShell(credentials, identity) + + # Mock certificate variable check and teams connection + execute_calls = [] + + def mock_execute_side_effect(command, json_parse=False): + execute_calls.append(command) + if "Write-Output $certificate" in command: + return "certificate_content" # Non-empty means certificate exists + elif "Connect-MicrosoftTeams" in command: + return {"TenantId": "test-tenant-id", "Account": "test-account"} + return "" + + session.execute = MagicMock(side_effect=mock_execute_side_effect) + session.test_teams_certificate_connection = MagicMock( + return_value={"success": True} + ) + + result = session.connect_microsoft_teams() + assert result == {"success": True} + + session.test_teams_certificate_connection.assert_called_once() + + session.close() + + @patch("subprocess.Popen") + def test_connect_exchange_online_certificate_auth(self, mock_popen): + """Test connect_exchange_online method with certificate authentication""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + + credentials = M365Credentials() + identity = M365IdentityInfo() + session = M365PowerShell(credentials, identity) + + # Mock certificate variable check and exchange connection + execute_calls = [] + + def mock_execute_side_effect(command, json_parse=False): + execute_calls.append(command) + if "Write-Output $certificate" in command: + return "certificate_content" # Non-empty means certificate exists + return "" + + session.execute = MagicMock(side_effect=mock_execute_side_effect) + session.test_exchange_certificate_connection = MagicMock(return_value=True) + + result = session.connect_exchange_online() + assert result is True + + session.test_exchange_certificate_connection.assert_called_once() + + session.close() + + @patch("subprocess.Popen") + def test_clean_certificate_content_basic(self, mock_popen): + """Test clean_certificate_content method with basic certificate content""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_process.returncode = 0 + + session = M365PowerShell( + M365Credentials( + client_id="test_client_id", + client_secret="test_secret", + tenant_id="test_tenant_id", + tenant_domains=["contoso.com"], + ), + M365IdentityInfo( + tenant_id="test_tenant_id", + tenant_domain="contoso.com", + tenant_domains=["contoso.com"], + identity_id="test_identity_id", + identity_type="Service Principal", + ), + ) + + # Test basic certificate content cleaning + cert_content = "LS0tLS1CRUdJTi\nBFUlRJRklD\rQVRFLS0tLS0\n" + expected = "LS0tLS1CRUdJTiBFUlRJRklDQVRFLS0tLS0" + + result = session.clean_certificate_content(cert_content) + + assert result == expected + session.close() + + @patch("subprocess.Popen") + def test_clean_certificate_content_with_spaces(self, mock_popen): + """Test clean_certificate_content method with spaces in certificate content""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_process.returncode = 0 + + session = M365PowerShell( + M365Credentials( + client_id="test_client_id", + client_secret="test_secret", + tenant_id="test_tenant_id", + tenant_domains=["contoso.com"], + ), + M365IdentityInfo( + tenant_id="test_tenant_id", + tenant_domain="contoso.com", + tenant_domains=["contoso.com"], + identity_id="test_identity_id", + identity_type="Service Principal", + ), + ) + + # Test certificate content with spaces + cert_content = " LS0tLS1CRUdJTi BFUlRJRklD QVRFLS0tLS0 " + expected = "LS0tLS1CRUdJTiBFUlRJRklDQVRFLS0tLS0" + + result = session.clean_certificate_content(cert_content) + + assert result == expected + session.close() + + @patch("subprocess.Popen") + def test_clean_certificate_content_empty(self, mock_popen): + """Test clean_certificate_content method with empty certificate content""" + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_process.returncode = 0 + + session = M365PowerShell( + M365Credentials( + client_id="test_client_id", + client_secret="test_secret", + tenant_id="test_tenant_id", + tenant_domains=["contoso.com"], + ), + M365IdentityInfo( + tenant_id="test_tenant_id", + tenant_domain="contoso.com", + tenant_domains=["contoso.com"], + identity_id="test_identity_id", + identity_type="Service Principal", + ), + ) + + # Test empty certificate content + cert_content = "" + expected = "" + + result = session.clean_certificate_content(cert_content) + + assert result == expected + session.close() + + @patch("subprocess.Popen") + def test_init_credential_certificate_auth_with_domains(self, mock_popen): + """Test init_credential method with certificate authentication and tenant domains""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_process.returncode = 0 + + executed_commands = [] + + def mock_execute(command): + executed_commands.append(command) + if "Error creating certificate" in command: + return None # No error + return "" + + # Create session with non-certificate credentials first + session = M365PowerShell( + M365Credentials( + client_id="test_client_id", + client_secret="test_secret", + tenant_id="test_tenant_id", + tenant_domains=["contoso.com", "subdomain.contoso.com"], + ), + M365IdentityInfo( + tenant_id="test_tenant_id", + tenant_domain="contoso.com", + tenant_domains=["contoso.com", "subdomain.contoso.com"], + identity_id="test_identity_id", + identity_type="Service Principal with Certificate", + ), + ) + + # Mock methods before calling init_credential + session.execute = MagicMock(side_effect=mock_execute) + session.sanitize = MagicMock(side_effect=lambda x: x) + session.clean_certificate_content = MagicMock(return_value=certificate_content) + + # Now test certificate authentication + session.init_credential( + M365Credentials( + client_id="test_client_id", + tenant_id="test_tenant_id", + certificate_content=certificate_content, + tenant_domains=["contoso.com", "subdomain.contoso.com"], + ) + ) + + # Verify that certificate content was cleaned + session.clean_certificate_content.assert_called_once_with(certificate_content) + + # Verify certificate creation commands were executed + assert any( + "$certBytes = [Convert]::FromBase64String" in cmd + for cmd in executed_commands + ) + assert any( + "$certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2" + in cmd + for cmd in executed_commands + ) + assert any('$clientID = "test_client_id"' in cmd for cmd in executed_commands) + assert any('$tenantID = "test_tenant_id"' in cmd for cmd in executed_commands) + assert any('$tenantDomain = "contoso.com"' in cmd for cmd in executed_commands) + + session.close() + + @patch("subprocess.Popen") + def test_test_credentials_certificate_auth_with_or_logic(self, mock_popen): + """Test test_credentials method with certificate auth using OR logic between Teams and Exchange""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_process.returncode = 0 + + # Create session with non-certificate credentials first + session = M365PowerShell( + M365Credentials( + client_id="test_client_id", + client_secret="test_secret", + tenant_id="test_tenant_id", + tenant_domains=["contoso.com"], + ), + M365IdentityInfo( + tenant_id="test_tenant_id", + tenant_domain="contoso.com", + tenant_domains=["contoso.com"], + identity_id="test_identity_id", + identity_type="Service Principal with Certificate", + ), + ) + + # Mock that Teams connection fails but Exchange succeeds + session.test_teams_certificate_connection = MagicMock(return_value=False) + session.test_exchange_certificate_connection = MagicMock(return_value=True) + + result = session.test_credentials( + M365Credentials( + client_id="test_client_id", + tenant_id="test_tenant_id", + certificate_content=certificate_content, + tenant_domains=["contoso.com"], + ) + ) + + assert result is True + session.test_teams_certificate_connection.assert_called_once() + session.test_exchange_certificate_connection.assert_called_once() + + session.close() + + @patch("subprocess.Popen") + def test_test_credentials_certificate_auth_both_fail(self, mock_popen): + """Test test_credentials method with certificate auth when both Teams and Exchange fail""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + mock_process = MagicMock() + mock_popen.return_value = mock_process + mock_process.returncode = 0 + + # Create session with non-certificate credentials first + session = M365PowerShell( + M365Credentials( + client_id="test_client_id", + client_secret="test_secret", + tenant_id="test_tenant_id", + tenant_domains=["contoso.com"], + ), + M365IdentityInfo( + tenant_id="test_tenant_id", + tenant_domain="contoso.com", + tenant_domains=["contoso.com"], + identity_id="test_identity_id", + identity_type="Service Principal with Certificate", + ), + ) + + # Mock that both connections fail + session.test_teams_certificate_connection = MagicMock(return_value=False) + session.test_exchange_certificate_connection = MagicMock(return_value=False) + + # Even when both fail, the method should return True (this is the intended logic) + result = session.test_credentials( + M365Credentials( + client_id="test_client_id", + tenant_id="test_tenant_id", + certificate_content=certificate_content, + tenant_domains=["contoso.com"], + ) + ) + + assert result is True + session.test_teams_certificate_connection.assert_called_once() + session.test_exchange_certificate_connection.assert_called_once() + + session.close() diff --git a/tests/providers/m365/m365_fixtures.py b/tests/providers/m365/m365_fixtures.py index f985f94b6a..2c1a322ece 100644 --- a/tests/providers/m365/m365_fixtures.py +++ b/tests/providers/m365/m365_fixtures.py @@ -1,5 +1,6 @@ +from unittest.mock import MagicMock + from azure.identity import DefaultAzureCredential -from mock import MagicMock from prowler.providers.m365.m365_provider import M365Provider from prowler.providers.m365.models import ( diff --git a/tests/providers/m365/m365_provider_test.py b/tests/providers/m365/m365_provider_test.py index 0f629d21a9..0af2abc7c8 100644 --- a/tests/providers/m365/m365_provider_test.py +++ b/tests/providers/m365/m365_provider_test.py @@ -1,15 +1,16 @@ +import base64 import os -from unittest.mock import patch +from unittest.mock import MagicMock, mock_open, patch from uuid import uuid4 import pytest from azure.core.credentials import AccessToken from azure.identity import ( + CertificateCredential, ClientSecretCredential, DefaultAzureCredential, InteractiveBrowserCredential, ) -from mock import MagicMock from prowler.config.config import ( default_config_file_path, @@ -18,15 +19,29 @@ from prowler.config.config import ( ) from prowler.providers.common.models import Connection from prowler.providers.m365.exceptions.exceptions import ( + M365BrowserAuthNoFlagError, + M365BrowserAuthNoTenantIDError, + M365ClientIdAndClientSecretNotBelongingToTenantIdError, + M365ConfigCredentialsError, + M365CredentialsUnavailableError, + M365DefaultAzureCredentialError, + M365EnvironmentVariableError, + M365GetTokenIdentityError, M365HTTPResponseError, M365InvalidProviderIdError, M365MissingEnvironmentCredentialsError, M365NoAuthenticationMethodError, + M365NotTenantIdButClientIdAndClientSecretError, + M365NotValidCertificateContentError, + M365NotValidCertificatePathError, M365NotValidClientIdError, M365NotValidClientSecretError, M365NotValidPasswordError, M365NotValidTenantIdError, M365NotValidUserError, + M365TenantIdAndClientIdNotBelongingToClientSecretError, + M365TenantIdAndClientSecretNotBelongingToClientIdError, + M365UserCredentialsError, M365UserNotBelongingToTenantError, ) from prowler.providers.m365.m365_provider import M365Provider @@ -296,6 +311,10 @@ class TestM365Provider: patch( "prowler.providers.m365.m365_provider.GraphServiceClient" ) as mock_graph_client, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), patch( "prowler.providers.m365.m365_provider.M365Provider.setup_identity", return_value=M365IdentityInfo( @@ -343,6 +362,10 @@ class TestM365Provider: patch( "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" ) as mock_validate_static_credentials, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), patch( "prowler.providers.m365.m365_provider.M365Provider.setup_identity", return_value=M365IdentityInfo( @@ -378,9 +401,15 @@ class TestM365Provider: def test_test_connection_tenant_id_client_id_client_secret_no_user_password( self, ): - with patch( - "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" - ) as mock_validate_static_credentials: + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" + ) as mock_validate_static_credentials, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), + ): mock_validate_static_credentials.side_effect = M365NotValidUserError( file=os.path.basename(__file__), message="The provided M365 User is not valid.", @@ -403,9 +432,15 @@ class TestM365Provider: def test_test_connection_tenant_id_client_id_client_secret_user_no_password( self, ): - with patch( - "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" - ) as mock_validate_static_credentials: + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" + ) as mock_validate_static_credentials, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), + ): mock_validate_static_credentials.side_effect = M365NotValidPasswordError( file=os.path.basename(__file__), message="The provided M365 Password is not valid.", @@ -426,9 +461,15 @@ class TestM365Provider: assert "The provided M365 Password is not valid." in str(exception.value) def test_test_connection_with_httpresponseerror(self): - with patch( - "prowler.providers.m365.m365_provider.M365Provider.setup_session" - ) as mock_setup_session: + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), + ): mock_setup_session.side_effect = M365HTTPResponseError( file="test_file", original_exception="Simulated HttpResponseError" ) @@ -446,9 +487,15 @@ class TestM365Provider: ) def test_test_connection_with_exception(self): - with patch( - "prowler.providers.m365.m365_provider.M365Provider.setup_session" - ) as mock_setup_session: + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), + ): mock_setup_session.side_effect = Exception("Simulated Exception") with pytest.raises(Exception) as exception: @@ -466,7 +513,7 @@ class TestM365Provider: assert exception.type == M365NoAuthenticationMethodError assert ( - "M365 provider requires at least one authentication method set: [--env-auth | --az-cli-auth | --sp-env-auth | --browser-auth]" + "M365 provider requires at least one authentication method set: [--env-auth | --az-cli-auth | --sp-env-auth | --browser-auth | --certificate-auth]" in exception.value.args[0] ) @@ -503,9 +550,15 @@ class TestM365Provider: def test_test_connection_user_not_belonging_to_tenant( self, ): - with patch( - "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" - ) as mock_validate_static_credentials: + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" + ) as mock_validate_static_credentials, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), + ): mock_validate_static_credentials.side_effect = M365UserNotBelongingToTenantError( file=os.path.basename(__file__), message="The provided M365 User does not belong to the specified tenant.", @@ -559,24 +612,30 @@ class TestM365Provider: user="test@example.com", password="test_password", ) - assert "The provided Client Secret is not valid." in str(exception.value) + assert ( + "You must provide a client secret, certificate content or certificate path. Please check your credentials and try again." + in str(exception.value) + ) def test_validate_arguments_missing_env_credentials(self): - with pytest.raises(M365MissingEnvironmentCredentialsError) as exception: + with pytest.raises(M365ConfigCredentialsError) as exception: M365Provider.validate_arguments( az_cli_auth=False, sp_env_auth=False, env_auth=True, browser_auth=False, - tenant_id=None, + certificate_auth=False, + tenant_id="test_tenant_id", client_id="test_client_id", - client_secret="test_secret", + client_secret=None, user=None, password=None, + certificate_content=None, + certificate_path=None, ) assert ( - "M365 provider requires AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_TENANT_ID, M365_USER and M365_PASSWORD environment variables to be set when using --env-auth" + "You must provide a valid set of credentials. Please check your credentials and try again." in str(exception.value) ) @@ -588,6 +647,10 @@ class TestM365Provider: patch( "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" ) as mock_validate_static_credentials, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), patch( "prowler.providers.m365.m365_provider.M365Provider.setup_identity", return_value=M365IdentityInfo( @@ -742,6 +805,10 @@ class TestM365Provider: patch( "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials" ) as mock_validate_static_credentials, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), patch( "prowler.providers.m365.m365_provider.M365Provider.setup_identity", return_value=M365IdentityInfo( @@ -780,3 +847,1287 @@ class TestM365Provider: f"The provider ID {provider_id} does not match any of the service principal tenant domains: contoso.onmicrosoft.com, contoso.com" in str(exception.value) ) + + def test_m365_provider_certificate_auth(self): + """Test M365 Provider initialization with certificate authentication""" + tenant_id = None + client_id = None + client_secret = None + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + fixer_config = load_and_validate_config_file( + "m365", default_fixer_config_file_path + ) + azure_region = "M365Global" + + # Mock certificate credential + mock_cert_credential = MagicMock() + mock_cert_credential.__class__ = CertificateCredential + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + return_value=mock_cert_credential, + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="Service Principal with Certificate", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + certificate_thumbprint="ABC123", + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_powershell", + return_value=M365Credentials( + client_id=CLIENT_ID, + tenant_id=TENANT_ID, + certificate_content=certificate_content, + ), + ), + ): + m365_provider = M365Provider( + sp_env_auth=False, + az_cli_auth=False, + browser_auth=False, + env_auth=False, + certificate_auth=True, + tenant_id=tenant_id, + client_id=client_id, + client_secret=client_secret, + certificate_content=certificate_content, + region=azure_region, + config_path=default_config_file_path, + fixer_config=fixer_config, + ) + + assert m365_provider.region_config == M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + assert ( + m365_provider.identity.identity_type + == "Service Principal with Certificate" + ) + assert m365_provider.session == mock_cert_credential + + def test_check_service_principal_creds_env_vars_missing_client_id(self): + """Test check_service_principal_creds_env_vars with missing AZURE_CLIENT_ID""" + with ( + patch.dict(os.environ, {}, clear=True), + pytest.raises(M365EnvironmentVariableError) as exception, + ): + M365Provider.check_service_principal_creds_env_vars() + + assert exception.type == M365EnvironmentVariableError + assert ( + "Missing environment variable AZURE_CLIENT_ID required to authenticate." + in str(exception.value) + ) + + def test_check_service_principal_creds_env_vars_missing_tenant_id(self): + """Test check_service_principal_creds_env_vars with missing AZURE_TENANT_ID""" + with ( + patch.dict(os.environ, {"AZURE_CLIENT_ID": "test_client_id"}, clear=True), + pytest.raises(M365EnvironmentVariableError) as exception, + ): + M365Provider.check_service_principal_creds_env_vars() + + assert exception.type == M365EnvironmentVariableError + assert ( + "Missing environment variable AZURE_TENANT_ID required to authenticate." + in str(exception.value) + ) + + def test_check_service_principal_creds_env_vars_missing_client_secret(self): + """Test check_service_principal_creds_env_vars with missing AZURE_CLIENT_SECRET""" + with ( + patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": "test_client_id", + "AZURE_TENANT_ID": "test_tenant_id", + }, + clear=True, + ), + pytest.raises(M365EnvironmentVariableError) as exception, + ): + M365Provider.check_service_principal_creds_env_vars() + + assert exception.type == M365EnvironmentVariableError + assert ( + "Missing environment variable AZURE_CLIENT_SECRET required to authenticate." + in str(exception.value) + ) + + def test_check_service_principal_creds_env_vars_success(self): + """Test check_service_principal_creds_env_vars with all required variables""" + with patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": "test_client_id", + "AZURE_TENANT_ID": "test_tenant_id", + "AZURE_CLIENT_SECRET": "test_client_secret", + }, + ): + # Should not raise any exception + M365Provider.check_service_principal_creds_env_vars() + + def test_check_certificate_creds_env_vars_missing_client_id(self): + """Test check_certificate_creds_env_vars with missing AZURE_CLIENT_ID""" + with ( + patch.dict(os.environ, {}, clear=True), + pytest.raises(M365EnvironmentVariableError) as exception, + ): + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + assert exception.type == M365EnvironmentVariableError + assert ( + "Missing environment variable AZURE_CLIENT_ID required to authenticate." + in str(exception.value) + ) + + def test_check_certificate_creds_env_vars_missing_tenant_id(self): + """Test check_certificate_creds_env_vars with missing AZURE_TENANT_ID""" + with ( + patch.dict(os.environ, {"AZURE_CLIENT_ID": "test_client_id"}, clear=True), + pytest.raises(M365EnvironmentVariableError) as exception, + ): + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + assert exception.type == M365EnvironmentVariableError + assert ( + "Missing environment variable AZURE_TENANT_ID required to authenticate." + in str(exception.value) + ) + + def test_check_certificate_creds_env_vars_missing_certificate_content(self): + """Test check_certificate_creds_env_vars with missing M365_CERTIFICATE_CONTENT""" + with ( + patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": "test_client_id", + "AZURE_TENANT_ID": "test_tenant_id", + }, + clear=True, + ), + pytest.raises(M365EnvironmentVariableError) as exception, + ): + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + assert exception.type == M365EnvironmentVariableError + assert ( + "Missing environment variable M365_CERTIFICATE_CONTENT required to authenticate." + in str(exception.value) + ) + + def test_check_certificate_creds_env_vars_missing_certificate_content_but_certificate_path( + self, + ): + """Test check_certificate_creds_env_vars with missing M365_CERTIFICATE_CONTENT""" + with patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": "test_client_id", + "AZURE_TENANT_ID": "test_tenant_id", + }, + clear=True, + ): + # This should not raise an exception since check_certificate_content=False + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=False + ) + + def test_check_certificate_creds_env_vars_success(self): + """Test check_certificate_creds_env_vars with all required variables""" + with patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": "test_client_id", + "AZURE_TENANT_ID": "test_tenant_id", + "M365_CERTIFICATE_CONTENT": base64.b64encode( + b"fake_certificate" + ).decode("utf-8"), + }, + ): + # Should not raise any exception + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + def test_setup_powershell_env_auth_missing_credentials(self): + """Test setup_powershell with env_auth but missing environment variables""" + with ( + patch.dict(os.environ, {}, clear=True), + pytest.raises(M365MissingEnvironmentCredentialsError) as exception, + ): + M365Provider.setup_powershell( + env_auth=True, + identity=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ), + ) + + assert exception.type == M365MissingEnvironmentCredentialsError + assert ( + "Missing M365_USER or M365_PASSWORD environment variables required for credentials authentication." + in str(exception.value) + ) + + def test_setup_powershell_env_auth_success(self): + """Test setup_powershell with env_auth and valid environment variables""" + with ( + patch.dict( + os.environ, + { + "M365_USER": "test@example.com", + "M365_PASSWORD": "password", + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_CLIENT_SECRET": CLIENT_SECRET, + "AZURE_TENANT_ID": TENANT_ID, + }, + ), + patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.test_credentials", + return_value=True, + ), + ): + result = M365Provider.setup_powershell( + env_auth=True, + identity=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ), + ) + + assert result.user == "test@example.com" + assert result.passwd == "password" + assert result.client_id == CLIENT_ID + + def test_setup_powershell_sp_env_auth_success(self): + """Test setup_powershell with sp_env_auth and valid environment variables""" + with ( + patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_CLIENT_SECRET": CLIENT_SECRET, + "AZURE_TENANT_ID": TENANT_ID, + }, + ), + patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.test_credentials", + return_value=True, + ), + ): + result = M365Provider.setup_powershell( + sp_env_auth=True, + identity=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="Service Principal", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ), + ) + + assert result.client_id == CLIENT_ID + assert result.client_secret == CLIENT_SECRET + assert result.tenant_id == TENANT_ID + + def test_setup_powershell_certificate_auth_success(self): + """Test setup_powershell with certificate_auth and valid environment variables""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + with ( + patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_TENANT_ID": TENANT_ID, + "M365_CERTIFICATE_CONTENT": certificate_content, + }, + ), + patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.test_credentials", + return_value=True, + ), + ): + identity = M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="Service Principal with Certificate", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ) + + result = M365Provider.setup_powershell( + certificate_auth=True, + identity=identity, + ) + + assert result.client_id == CLIENT_ID + assert result.tenant_id == TENANT_ID + assert result.certificate_content == certificate_content + assert identity.identity_type == "Service Principal with Certificate" + + def test_setup_powershell_invalid_credentials(self): + """Test setup_powershell with invalid credentials""" + credentials_dict = { + "user": "test@example.com", + "password": "test_password", + "client_id": "test_client_id", + "tenant_id": "test_tenant_id", + "client_secret": "test_client_secret", + } + + with ( + patch( + "prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.test_credentials", + return_value=False, + ), + pytest.raises(M365UserCredentialsError) as exception, + ): + M365Provider.setup_powershell( + env_auth=False, + m365_credentials=credentials_dict, + identity=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="User", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ), + ) + + assert exception.type == M365UserCredentialsError + assert "The provided User credentials are not valid." in str(exception.value) + + def test_validate_arguments_browser_auth_without_tenant_id(self): + """Test validate_arguments with browser_auth but missing tenant_id""" + with pytest.raises(M365BrowserAuthNoTenantIDError) as exception: + M365Provider.validate_arguments( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=True, + certificate_auth=False, + tenant_id=None, + client_id=None, + client_secret=None, + user=None, + password=None, + certificate_content=None, + certificate_path=None, + ) + + assert exception.type == M365BrowserAuthNoTenantIDError + assert ( + "M365 Tenant ID (--tenant-id) is required for browser authentication mode" + in str(exception.value) + ) + + def test_validate_arguments_tenant_id_without_browser_flag(self): + """Test validate_arguments with tenant_id but without browser auth flag""" + with pytest.raises(M365BrowserAuthNoFlagError) as exception: + M365Provider.validate_arguments( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=False, + tenant_id=TENANT_ID, + client_id=None, + client_secret=None, + user=None, + password=None, + certificate_content=None, + certificate_path=None, + ) + + assert exception.type == M365BrowserAuthNoFlagError + assert "browser authentication flag (--browser-auth) not found" in str( + exception.value + ) + + def test_validate_arguments_missing_tenant_id_with_credentials(self): + """Test validate_arguments with client credentials but missing tenant_id""" + with pytest.raises(M365NotTenantIdButClientIdAndClientSecretError) as exception: + M365Provider.validate_arguments( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=False, + tenant_id=None, + client_id=CLIENT_ID, + client_secret=CLIENT_SECRET, + user=None, + password=None, + certificate_content=None, + certificate_path=None, + ) + + assert exception.type == M365NotTenantIdButClientIdAndClientSecretError + assert "Tenant Id is required for M365 static credentials" in str( + exception.value + ) + + def test_test_connection_certificate_auth(self): + """Test test_connection with certificate authentication""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch("prowler.providers.m365.m365_provider.M365Provider.setup_powershell"), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="Service Principal with Certificate", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_static_credentials", + return_value={ + "tenant_id": TENANT_ID, + "client_id": CLIENT_ID, + "client_secret": None, + "user": None, + "password": None, + "certificate_content": certificate_content, + }, + ), + ): + mock_session = MagicMock() + mock_setup_session.return_value = mock_session + + test_connection = M365Provider.test_connection( + certificate_auth=True, + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_content=certificate_content, + region="M365Global", + raise_on_exception=False, + provider_id="test.onmicrosoft.com", + ) + + assert isinstance(test_connection, Connection) + assert test_connection.is_connected + assert test_connection.error is None + + def test_test_connection_get_token_identity_error(self): + """Test test_connection when setup_identity returns None""" + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session" + ) as mock_setup_session, + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=None, + ), + pytest.raises(M365GetTokenIdentityError) as exception, + ): + mock_session = MagicMock() + mock_setup_session.return_value = mock_session + + M365Provider.test_connection( + az_cli_auth=True, + raise_on_exception=True, + ) + + assert exception.type == M365GetTokenIdentityError + assert "Failed to retrieve M365 identity" in str(exception.value) + + def test_validate_static_credentials_client_id_secret_tenant_error(self): + """Test validate_static_credentials with client/secret/tenant mismatch errors""" + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.verify_client", + side_effect=M365NotValidTenantIdError( + file="test", message="Invalid tenant" + ), + ), + pytest.raises( + M365ClientIdAndClientSecretNotBelongingToTenantIdError + ) as exception, + ): + M365Provider.validate_static_credentials( + tenant_id=str(uuid4()), + client_id=str(uuid4()), + client_secret="test_secret", + user="test@example.com", + password="test_password", + ) + + assert exception.type == M365ClientIdAndClientSecretNotBelongingToTenantIdError + assert ( + "The provided Client ID and Client Secret do not belong to the specified Tenant ID." + in str(exception.value) + ) + + def test_validate_static_credentials_tenant_secret_client_error(self): + """Test validate_static_credentials with tenant/secret/client mismatch errors""" + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.verify_client", + side_effect=M365NotValidClientIdError( + file="test", message="Invalid client ID" + ), + ), + pytest.raises( + M365TenantIdAndClientSecretNotBelongingToClientIdError + ) as exception, + ): + M365Provider.validate_static_credentials( + tenant_id=str(uuid4()), + client_id=str(uuid4()), + client_secret="test_secret", + user="test@example.com", + password="test_password", + ) + + assert exception.type == M365TenantIdAndClientSecretNotBelongingToClientIdError + assert ( + "The provided Tenant ID and Client Secret do not belong to the specified Client ID." + in str(exception.value) + ) + + def test_validate_static_credentials_tenant_client_secret_error(self): + """Test validate_static_credentials with tenant/client/secret mismatch errors""" + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.verify_client", + side_effect=M365NotValidClientSecretError( + file="test", message="Invalid client secret" + ), + ), + pytest.raises( + M365TenantIdAndClientIdNotBelongingToClientSecretError + ) as exception, + ): + M365Provider.validate_static_credentials( + tenant_id=str(uuid4()), + client_id=str(uuid4()), + client_secret="test_secret", + user="test@example.com", + password="test_password", + ) + + assert exception.type == M365TenantIdAndClientIdNotBelongingToClientSecretError + assert ( + "The provided Tenant ID and Client ID do not belong to the specified Client Secret." + in str(exception.value) + ) + + def test_test_connection_default_azure_credential_error(self): + """Test test_connection with DefaultAzureCredential error in exception handling""" + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + side_effect=M365DefaultAzureCredentialError( + file="test", + original_exception=Exception("Default credential error"), + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + pytest.raises(M365DefaultAzureCredentialError) as exception, + ): + M365Provider.test_connection( + az_cli_auth=True, + raise_on_exception=True, + ) + + assert exception.type == M365DefaultAzureCredentialError + + def test_test_connection_credentials_unavailable_error_handling(self): + """Test test_connection with CredentialsUnavailableError in exception handling""" + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + side_effect=M365CredentialsUnavailableError( + file="test", original_exception=Exception("Credentials unavailable") + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.validate_arguments" + ), + pytest.raises(M365CredentialsUnavailableError) as exception, + ): + M365Provider.test_connection( + sp_env_auth=True, + raise_on_exception=True, + ) + + assert exception.type == M365CredentialsUnavailableError + + def test_setup_session_certificate_auth_success(self): + """Test setup_session method with certificate authentication - success""" + with ( + patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_TENANT_ID": TENANT_ID, + "M365_CERTIFICATE_CONTENT": base64.b64encode( + b"fake_certificate" + ).decode("utf-8"), + }, + ), + patch( + "prowler.providers.m365.m365_provider.CertificateCredential" + ) as mock_cert_credential, + ): + mock_credential_instance = MagicMock() + mock_cert_credential.return_value = mock_credential_instance + + region_config = M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + + result = M365Provider.setup_session( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=True, + certificate_path=None, + tenant_id=None, + m365_credentials=None, + region_config=region_config, + ) + + assert result == mock_credential_instance + mock_cert_credential.assert_called_once_with( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_data=base64.b64decode( + base64.b64encode(b"fake_certificate").decode("utf-8") + ), + ) + + def test_setup_session_certificate_auth_client_authentication_error(self): + """Test setup_session method with certificate authentication - ClientAuthenticationError""" + from azure.core.exceptions import ClientAuthenticationError + + from prowler.providers.m365.exceptions.exceptions import M365SetUpSessionError + + with ( + patch.dict( + os.environ, + { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_TENANT_ID": TENANT_ID, + "M365_CERTIFICATE_CONTENT": base64.b64encode( + b"fake_certificate" + ).decode("utf-8"), + }, + ), + patch( + "prowler.providers.m365.m365_provider.CertificateCredential", + side_effect=ClientAuthenticationError("Authentication failed"), + ), + pytest.raises(M365SetUpSessionError) as exception, + ): + region_config = M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + + M365Provider.setup_session( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=True, + certificate_path=None, + tenant_id=None, + m365_credentials=None, + region_config=region_config, + ) + + # The error should be wrapped in M365SetUpSessionError and contain the ClientAuthenticationError + assert exception.type == M365SetUpSessionError + assert "M365ClientAuthenticationError" in str(exception.value) + + def test_setup_session_certificate_auth_with_static_credentials(self): + """Test setup_session method with certificate authentication using static credentials""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + m365_credentials = { + "tenant_id": TENANT_ID, + "client_id": CLIENT_ID, + "client_secret": CLIENT_SECRET, + "user": None, + "password": None, + "certificate_content": certificate_content, + } + + with ( + patch( + "prowler.providers.m365.m365_provider.CertificateCredential" + ) as mock_credential, + ): + mock_credential_instance = MagicMock() + mock_credential.return_value = mock_credential_instance + + region_config = M365RegionConfig( + name="M365Global", + authority=None, + base_url="https://graph.microsoft.com", + credential_scopes=["https://graph.microsoft.com/.default"], + ) + + result = M365Provider.setup_session( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=False, + certificate_path=None, + tenant_id=None, + m365_credentials=m365_credentials, + region_config=region_config, + ) + + assert result == mock_credential_instance + mock_credential.assert_called_once_with( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_data=base64.b64decode(certificate_content), + ) + + def test_setup_powershell_certificate_auth_missing_env_vars(self): + """Test setup_powershell with certificate_auth but missing environment variables""" + from pydantic.v1.error_wrappers import ValidationError + + with (patch.dict(os.environ, {}, clear=True),): + identity = M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="Service Principal with Certificate", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + tenant_domains=["test.onmicrosoft.com"], + location=LOCATION, + ) + + # Should raise ValidationError when trying to create credentials with None values + with pytest.raises(ValidationError) as exc_info: + M365Provider.setup_powershell( + certificate_auth=True, + identity=identity, + ) + + # Verify the error is about None values not being allowed + assert "none is not an allowed value" in str(exc_info.value).lower() + + def test_validate_arguments_certificate_auth_valid(self): + """Test validate_arguments method with valid certificate authentication arguments""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + # Should not raise any exception + M365Provider.validate_arguments( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=True, + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + client_secret=None, + user=None, + password=None, + certificate_content=certificate_content, + certificate_path=None, + ) + + def test_validate_arguments_certificate_auth_missing_certificate_content(self): + """Test validate_arguments method with certificate auth but missing certificate content""" + with pytest.raises(M365ConfigCredentialsError) as exception: + M365Provider.validate_arguments( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=False, + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + client_secret=None, + user=None, + password=None, + certificate_content=None, + certificate_path=None, + ) + + assert "You must provide a valid set of credentials" in str(exception.value) + + def test_print_credentials_with_certificate(self): + """Test print_credentials method with certificate authentication""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + # Mock certificate credential + mock_cert_credential = MagicMock() + mock_cert_credential.__class__ = CertificateCredential + + with ( + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_session", + return_value=mock_cert_credential, + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_identity", + return_value=M365IdentityInfo( + identity_id=IDENTITY_ID, + identity_type="Service Principal with Certificate", + tenant_id=TENANT_ID, + tenant_domain=DOMAIN, + location=LOCATION, + certificate_thumbprint="ABC123DEF456", + ), + ), + patch( + "prowler.providers.m365.m365_provider.M365Provider.setup_powershell", + return_value=M365Credentials( + client_id=CLIENT_ID, + tenant_id=TENANT_ID, + certificate_content=certificate_content, + ), + ), + patch( + "prowler.providers.m365.m365_provider.print_boxes" + ) as mock_print_boxes, + ): + m365_provider = M365Provider( + certificate_auth=True, + region="M365Global", + ) + + m365_provider.print_credentials() + + # Verify print_boxes was called + mock_print_boxes.assert_called_once() + args, _ = mock_print_boxes.call_args + report_lines = args[0] + + # Check that certificate thumbprint is in the output + cert_line_found = any( + "Certificate Thumbprint" in line for line in report_lines + ) + assert ( + cert_line_found + ), "Certificate thumbprint should be in printed credentials" + + def test_validate_static_credentials_invalid_certificate_content(self): + """Test validate_static_credentials method with invalid certificate content""" + invalid_cert_content = "invalid_base64_content" + + with pytest.raises(RuntimeError) as exception: + M365Provider.validate_static_credentials( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_content=invalid_cert_content, + ) + + assert "An unexpected error occurred" in str(exception.value) + + def test_validate_static_credentials_invalid_certificate_path(self): + """Test validate_static_credentials method with invalid certificate path""" + invalid_cert_path = "/non/existent/path/cert.pem" + + with pytest.raises(M365NotValidCertificatePathError) as exception: + M365Provider.validate_static_credentials( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_path=invalid_cert_path, + ) + + assert "certificate path is not valid" in str(exception.value) + + def test_validate_static_credentials_certificate_base64_validation_error(self): + """Test validate_static_credentials method with invalid base64 certificate content""" + invalid_cert_content = "not_valid_base64!@#$%" + + with pytest.raises(M365NotValidCertificateContentError) as exception: + M365Provider.validate_static_credentials( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_content=invalid_cert_content, + ) + + assert "certificate content is not valid base64 encoded data" in str( + exception.value + ) + + def test_validate_static_credentials_certificate_path_file_not_found(self): + """Test validate_static_credentials method with certificate path that doesn't exist""" + invalid_cert_path = "/totally/non/existent/path/cert.pem" + + with pytest.raises(M365NotValidCertificatePathError) as exception: + M365Provider.validate_static_credentials( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_path=invalid_cert_path, + ) + + assert "certificate path is not valid" in str(exception.value) + + def test_validate_static_credentials_valid_certificate_content(self): + """Test validate_static_credentials method with valid certificate content""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + with patch( + "prowler.providers.m365.m365_provider.M365Provider.verify_client" + ) as mock_verify: + mock_verify.return_value = None + + result = M365Provider.validate_static_credentials( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_content=certificate_content, + ) + + assert result["tenant_id"] == TENANT_ID + assert result["client_id"] == CLIENT_ID + assert result["certificate_content"] == certificate_content + mock_verify.assert_called_once_with( + TENANT_ID, CLIENT_ID, None, certificate_content, None + ) + + @patch("builtins.open", mock_open(read_data=b"fake_certificate_data")) + def test_validate_static_credentials_valid_certificate_path(self): + """Test validate_static_credentials method with valid certificate path""" + certificate_path = "/path/to/cert.pem" + + with patch( + "prowler.providers.m365.m365_provider.M365Provider.verify_client" + ) as mock_verify: + mock_verify.return_value = None + + result = M365Provider.validate_static_credentials( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_path=certificate_path, + ) + + assert result["tenant_id"] == TENANT_ID + assert result["client_id"] == CLIENT_ID + assert result["certificate_path"] == certificate_path + mock_verify.assert_called_once_with( + TENANT_ID, CLIENT_ID, None, b"fake_certificate_data", certificate_path + ) + + @patch("prowler.providers.m365.m365_provider.asyncio.get_event_loop") + @patch("prowler.providers.m365.m365_provider.GraphServiceClient") + @patch("prowler.providers.m365.m365_provider.CertificateCredential") + def test_verify_client_certificate_content_success( + self, mock_cert_cred, mock_graph, mock_loop + ): + """Test verify_client method with valid certificate content""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + # Mock the async call + mock_loop_instance = MagicMock() + mock_loop.return_value = mock_loop_instance + mock_loop_instance.run_until_complete.return_value = [{"id": "domain.com"}] + + # Mock credential and graph client + mock_credential = MagicMock() + mock_cert_cred.return_value = mock_credential + mock_client = MagicMock() + mock_graph.return_value = mock_client + + # Should not raise any exception + M365Provider.verify_client( + TENANT_ID, CLIENT_ID, None, certificate_content, None + ) + + mock_cert_cred.assert_called_once() + mock_graph.assert_called_once_with(credentials=mock_credential) + + @patch("prowler.providers.m365.m365_provider.asyncio.get_event_loop") + @patch("prowler.providers.m365.m365_provider.GraphServiceClient") + @patch("prowler.providers.m365.m365_provider.CertificateCredential") + def test_verify_client_certificate_content_failure( + self, mock_cert_cred, mock_graph, mock_loop + ): + """Test verify_client method with certificate content that fails validation""" + certificate_content = base64.b64encode(b"fake_certificate").decode("utf-8") + + # Mock the async call to return empty result (invalid certificate) + mock_loop_instance = MagicMock() + mock_loop.return_value = mock_loop_instance + mock_loop_instance.run_until_complete.return_value = None + + # Mock credential and graph client + mock_credential = MagicMock() + mock_cert_cred.return_value = mock_credential + mock_client = MagicMock() + mock_graph.return_value = mock_client + + with pytest.raises(RuntimeError) as exception: + M365Provider.verify_client( + TENANT_ID, CLIENT_ID, None, certificate_content, None + ) + + assert "certificate content is not valid" in str(exception.value) + + @patch("builtins.open", mock_open(read_data=b"fake_certificate_data")) + @patch("prowler.providers.m365.m365_provider.asyncio.get_event_loop") + @patch("prowler.providers.m365.m365_provider.GraphServiceClient") + @patch("prowler.providers.m365.m365_provider.CertificateCredential") + def test_verify_client_certificate_path_success( + self, mock_cert_cred, mock_graph, mock_loop + ): + """Test verify_client method with valid certificate path""" + certificate_path = "/path/to/cert.pem" + + # Mock the async call + mock_loop_instance = MagicMock() + mock_loop.return_value = mock_loop_instance + mock_loop_instance.run_until_complete.return_value = [{"id": "domain.com"}] + + # Mock credential and graph client + mock_credential = MagicMock() + mock_cert_cred.return_value = mock_credential + mock_client = MagicMock() + mock_graph.return_value = mock_client + + # Should not raise any exception + M365Provider.verify_client(TENANT_ID, CLIENT_ID, None, None, certificate_path) + + mock_cert_cred.assert_called_once() + mock_graph.assert_called_once_with(credentials=mock_credential) + + @patch("builtins.open", mock_open(read_data=b"fake_certificate_data")) + @patch("prowler.providers.m365.m365_provider.asyncio.get_event_loop") + @patch("prowler.providers.m365.m365_provider.GraphServiceClient") + @patch("prowler.providers.m365.m365_provider.CertificateCredential") + def test_verify_client_certificate_path_failure( + self, mock_cert_cred, mock_graph, mock_loop + ): + """Test verify_client method with certificate path that fails validation""" + certificate_path = "/path/to/cert.pem" + + # Mock the async call to return empty result (invalid certificate) + mock_loop_instance = MagicMock() + mock_loop.return_value = mock_loop_instance + mock_loop_instance.run_until_complete.return_value = None + + # Mock credential and graph client + mock_credential = MagicMock() + mock_cert_cred.return_value = mock_credential + mock_client = MagicMock() + mock_graph.return_value = mock_client + + with pytest.raises(RuntimeError) as exception: + M365Provider.verify_client( + TENANT_ID, CLIENT_ID, None, None, certificate_path + ) + + assert "certificate is not valid" in str(exception.value) + + def test_setup_session_certificate_auth_with_certificate_path(self): + """Test setup_session method with certificate authentication using certificate path""" + certificate_path = "/path/to/cert.pem" + mock_cert_data = b"fake_certificate_data" + + with ( + patch("builtins.open", mock_open(read_data=mock_cert_data)), + patch("prowler.providers.m365.m365_provider.getenv") as mock_getenv, + patch( + "prowler.providers.m365.m365_provider.CertificateCredential" + ) as mock_cert_cred, + ): + mock_getenv.side_effect = lambda var: { + "AZURE_TENANT_ID": TENANT_ID, + "AZURE_CLIENT_ID": CLIENT_ID, + }.get(var) + + mock_credential = MagicMock() + mock_cert_cred.return_value = mock_credential + + result = M365Provider.setup_session( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=True, + certificate_path=certificate_path, + tenant_id=None, + m365_credentials=None, + region_config=MagicMock(), + ) + + assert result == mock_credential + mock_cert_cred.assert_called_once_with( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_data=mock_cert_data, + ) + + def test_setup_session_certificate_auth_with_static_credentials_certificate_path( + self, + ): + """Test setup_session method with certificate authentication using static credentials with certificate path""" + certificate_path = "/path/to/cert.pem" + mock_cert_data = b"fake_certificate_data" + + m365_credentials = { + "tenant_id": TENANT_ID, + "client_id": CLIENT_ID, + "client_secret": None, + "user": None, + "password": None, + "certificate_content": None, + "certificate_path": certificate_path, + } + + with ( + patch("builtins.open", mock_open(read_data=mock_cert_data)), + patch( + "prowler.providers.m365.m365_provider.CertificateCredential" + ) as mock_cert_cred, + ): + mock_credential = MagicMock() + mock_cert_cred.return_value = mock_credential + + result = M365Provider.setup_session( + az_cli_auth=False, + sp_env_auth=False, + env_auth=False, + browser_auth=False, + certificate_auth=False, + certificate_path=None, + tenant_id=None, + m365_credentials=m365_credentials, + region_config=MagicMock(), + ) + + assert result == mock_credential + mock_cert_cred.assert_called_once_with( + tenant_id=TENANT_ID, + client_id=CLIENT_ID, + certificate_data=mock_cert_data, + ) + + def test_check_certificate_creds_env_vars_with_certificate_content_success(self): + """Test check_certificate_creds_env_vars method with certificate content check""" + with patch("prowler.providers.m365.m365_provider.getenv") as mock_getenv: + mock_getenv.side_effect = lambda var: { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_TENANT_ID": TENANT_ID, + "M365_CERTIFICATE_CONTENT": "fake_certificate_content", + }.get(var) + + # Should not raise any exception + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + def test_check_certificate_creds_env_vars_without_certificate_content_success(self): + """Test check_certificate_creds_env_vars method without certificate content check""" + with patch("prowler.providers.m365.m365_provider.getenv") as mock_getenv: + mock_getenv.side_effect = lambda var: { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_TENANT_ID": TENANT_ID, + }.get(var) + + # Should not raise any exception + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=False + ) + + def test_check_certificate_creds_env_vars_missing_client_id_with_certificate(self): + """Test check_certificate_creds_env_vars method missing client ID with certificate content""" + with patch("prowler.providers.m365.m365_provider.getenv") as mock_getenv: + mock_getenv.side_effect = lambda var: { + "AZURE_TENANT_ID": TENANT_ID, + "M365_CERTIFICATE_CONTENT": "fake_certificate_content", + }.get(var) + + with pytest.raises(M365EnvironmentVariableError) as exception: + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + assert "Missing environment variable AZURE_CLIENT_ID" in str( + exception.value + ) + + def test_check_certificate_creds_env_vars_missing_tenant_id_with_certificate(self): + """Test check_certificate_creds_env_vars method missing tenant ID with certificate content""" + with patch("prowler.providers.m365.m365_provider.getenv") as mock_getenv: + mock_getenv.side_effect = lambda var: { + "AZURE_CLIENT_ID": CLIENT_ID, + "M365_CERTIFICATE_CONTENT": "fake_certificate_content", + }.get(var) + + with pytest.raises(M365EnvironmentVariableError) as exception: + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + assert "Missing environment variable AZURE_TENANT_ID" in str( + exception.value + ) + + def test_check_certificate_creds_env_vars_missing_certificate_content_when_required( + self, + ): + """Test check_certificate_creds_env_vars method missing certificate content when required""" + with patch("prowler.providers.m365.m365_provider.getenv") as mock_getenv: + mock_getenv.side_effect = lambda var: { + "AZURE_CLIENT_ID": CLIENT_ID, + "AZURE_TENANT_ID": TENANT_ID, + }.get(var) + + with pytest.raises(M365EnvironmentVariableError) as exception: + M365Provider.check_certificate_creds_env_vars( + check_certificate_content=True + ) + + assert "Missing environment variable M365_CERTIFICATE_CONTENT" in str( + exception.value + ) From 3c94d3a56fe45686652851950975e7e0fbeeb4f5 Mon Sep 17 00:00:00 2001 From: sumit-tft <70506234+sumit-tft@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:07:35 +0530 Subject: [PATCH 05/30] fix(ui): disable See Compliance button until scan completes (#8487) Co-authored-by: Pablo Lara --- ui/CHANGELOG.md | 2 ++ ui/components/scans/table/scans/column-get-scans.tsx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index a067e0ecab..23d7bd0f29 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -11,6 +11,8 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🔄 Changed +- Disable `See Compliance` button until scan completes [(#8487)](https://github.com/prowler-cloud/prowler/pull/8487) + ### 🐞 Fixed ### ❌ Removed diff --git a/ui/components/scans/table/scans/column-get-scans.tsx b/ui/components/scans/table/scans/column-get-scans.tsx index f0b832e5d1..8a6b3fb8c6 100644 --- a/ui/components/scans/table/scans/column-get-scans.tsx +++ b/ui/components/scans/table/scans/column-get-scans.tsx @@ -123,7 +123,7 @@ export const ColumnGetScans: ColumnDef[] = [ return ( ); From 5572d476ad81550a151fe5c929c1f94239c00238 Mon Sep 17 00:00:00 2001 From: sumit-tft <70506234+sumit-tft@users.noreply.github.com> Date: Mon, 11 Aug 2025 14:17:10 +0530 Subject: [PATCH 06/30] fix(ui): adjust table headers to be single-line and consistent (#8480) --- ui/CHANGELOG.md | 1 + ui/components/findings/table/column-findings.tsx | 2 +- .../new-findings-table/table/column-new-findings-to-date.tsx | 2 +- ui/components/scans/table/scans/column-get-scans.tsx | 2 +- ui/components/ui/table/data-table-column-header.tsx | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 23d7bd0f29..72c52f4a86 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to the **Prowler UI** are documented in this file. - Disable `See Compliance` button until scan completes [(#8487)](https://github.com/prowler-cloud/prowler/pull/8487) ### 🐞 Fixed +- DataTable column headers set to single-line [(#8480)](https://github.com/prowler-cloud/prowler/pull/8480) ### ❌ Removed diff --git a/ui/components/findings/table/column-findings.tsx b/ui/components/findings/table/column-findings.tsx index 51e3d4625d..fb4040149d 100644 --- a/ui/components/findings/table/column-findings.tsx +++ b/ui/components/findings/table/column-findings.tsx @@ -228,7 +228,7 @@ export const ColumnFindings: ColumnDef[] = [ }, { accessorKey: "cloudProvider", - header: "Cloud provider", + header: "Cloud Provider", cell: ({ row }) => { const provider = getProviderData(row, "provider"); const alias = getProviderData(row, "alias"); diff --git a/ui/components/overview/new-findings-table/table/column-new-findings-to-date.tsx b/ui/components/overview/new-findings-table/table/column-new-findings-to-date.tsx index 348c1be8df..894fc48183 100644 --- a/ui/components/overview/new-findings-table/table/column-new-findings-to-date.tsx +++ b/ui/components/overview/new-findings-table/table/column-new-findings-to-date.tsx @@ -174,7 +174,7 @@ export const ColumnNewFindingsToDate: ColumnDef[] = [ }, { accessorKey: "cloudProvider", - header: "Cloud provider", + header: "Cloud Provider", cell: ({ row }) => { const provider = getProviderData(row, "provider"); const alias = getProviderData(row, "alias"); diff --git a/ui/components/scans/table/scans/column-get-scans.tsx b/ui/components/scans/table/scans/column-get-scans.tsx index 8a6b3fb8c6..310e1c3815 100644 --- a/ui/components/scans/table/scans/column-get-scans.tsx +++ b/ui/components/scans/table/scans/column-get-scans.tsx @@ -47,7 +47,7 @@ export const ColumnGetScans: ColumnDef[] = [ }, { accessorKey: "cloudProvider", - header: () =>

Cloud provider

, + header: () =>

Cloud Provider

, cell: ({ row }) => { const providerInfo = row.original.providerInfo; diff --git a/ui/components/ui/table/data-table-column-header.tsx b/ui/components/ui/table/data-table-column-header.tsx index a9a6c4beb5..6a61fdaec4 100644 --- a/ui/components/ui/table/data-table-column-header.tsx +++ b/ui/components/ui/table/data-table-column-header.tsx @@ -83,7 +83,7 @@ export const DataTableColumnHeader = ({ className="flex h-10 w-full items-center justify-between whitespace-nowrap bg-transparent px-0 text-left align-middle text-tiny font-semibold text-foreground-500 outline-none dark:text-slate-400" onPress={getToggleSortingHandler} > - {title} + {title} {renderSortIcon()} ); From d238050065bad4e8ef40b5caf8e75e3a0d01ca6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Mon, 11 Aug 2025 11:44:45 +0200 Subject: [PATCH 07/30] feat(azure/vm): add new check `vm_sufficient_daily_backup_retention_period` (#8200) Co-authored-by: MrCloudSec --- docs/tutorials/configuration_file.md | 1 + prowler/CHANGELOG.md | 1 + prowler/config/config.yaml | 3 + .../services/recovery/recovery_service.py | 72 +++- .../__init__.py | 0 ...aily_backup_retention_period.metadata.json | 30 ++ ...ufficient_daily_backup_retention_period.py | 51 +++ tests/providers/azure/azure_provider_test.py | 1 + ...ient_daily_backup_retention_period_test.py | 323 ++++++++++++++++++ 9 files changed, 478 insertions(+), 4 deletions(-) create mode 100644 prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/__init__.py create mode 100644 prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.metadata.json create mode 100644 prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.py create mode 100644 tests/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period_test.py diff --git a/docs/tutorials/configuration_file.md b/docs/tutorials/configuration_file.md index c4f48f395f..b99e5064d0 100644 --- a/docs/tutorials/configuration_file.md +++ b/docs/tutorials/configuration_file.md @@ -80,6 +80,7 @@ The following list includes all the Azure checks with configurable variables tha | `app_ensure_python_version_is_latest` | `python_latest_version` | String | | `app_ensure_java_version_is_latest` | `java_latest_version` | String | | `sqlserver_recommended_minimal_tls_version` | `recommended_minimal_tls_versions` | List of Strings | +| `vm_sufficient_daily_backup_retention_period` | `vm_backup_min_daily_retention_days` | Integer | | `vm_desired_sku_size` | `desired_vm_sku_sizes` | List of Strings | | `defender_attack_path_notifications_properly_configured` | `defender_attack_path_minimal_risk_level` | String | diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 2a1428ef18..76dc4976d1 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Added - Certificate authentication for M365 provider [(#8404)](https://github.com/prowler-cloud/prowler/pull/8404) +- `vm_sufficient_daily_backup_retention_period` check for Azure provider [(#8200)](https://github.com/prowler-cloud/prowler/pull/8200) ### Changed diff --git a/prowler/config/config.yaml b/prowler/config/config.yaml index 0613780bd2..7932131af6 100644 --- a/prowler/config/config.yaml +++ b/prowler/config/config.yaml @@ -459,6 +459,9 @@ azure: "Standard_DS3_v2", "Standard_D4s_v3", ] + # Azure VM Backup Configuration + # azure.vm_sufficient_daily_backup_retention_period + vm_backup_min_daily_retention_days: 7 # GCP Configuration gcp: diff --git a/prowler/providers/azure/services/recovery/recovery_service.py b/prowler/providers/azure/services/recovery/recovery_service.py index e39a6fc1f7..efc7630bf7 100644 --- a/prowler/providers/azure/services/recovery/recovery_service.py +++ b/prowler/providers/azure/services/recovery/recovery_service.py @@ -11,20 +11,30 @@ from prowler.providers.azure.lib.service.service import AzureService class BackupItem(BaseModel): - """Minimal BackupItem: only essential identifying and descriptive fields.""" + """Model that represents a backup item.""" id: str name: str workload_type: Optional[DataSourceType] + backup_policy_id: Optional[str] = None + + +class BackupPolicy(BaseModel): + """Model that represents a backup policy.""" + + id: str + name: str + retention_days: Optional[int] = None class BackupVault(BaseModel): - """Minimal BackupVault: only essential identifying fields and its backup items.""" + """Model that represents a backup vault.""" id: str name: str location: str backup_protected_items: dict[str, BackupItem] = Field(default_factory=dict) + backup_policies: dict[str, BackupPolicy] = Field(default_factory=dict) class Recovery(AzureService): @@ -71,6 +81,9 @@ class RecoveryBackup(AzureService): vault.backup_protected_items = self._get_backup_protected_items( subscription_name=subscription_name, vault=vault ) + vault.backup_policies = self._get_backup_policies( + subscription_name=subscription_name, vault=vault + ) def _get_backup_protected_items( self, subscription_name: str, vault: BackupVault @@ -95,7 +108,58 @@ class RecoveryBackup(AzureService): workload_type=( item_properties.workload_type if item_properties else None ), + backup_policy_id=( + item_properties.policy_id if item_properties else None + ), ) - except Exception as e: - logger.error(f"Recovery - Error getting backup protected items: {e}") + except Exception as error: + logger.error( + f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) return backup_protected_items_dict + + def _get_backup_policies( + self, subscription_name: str, vault: BackupVault + ) -> dict[str, BackupPolicy]: + """ + Retrieve all backup policies for a given vault. + """ + logger.info("Recovery - Getting backup policies...") + backup_policies_dict: dict[str, BackupPolicy] = {} + unique_backup_policies: set[str] = set() + try: + for item in vault.backup_protected_items.values(): + if item.backup_policy_id: + unique_backup_policies.add(item.backup_policy_id) + for policy_id in unique_backup_policies: + policy = self.clients[subscription_name].protection_policies.get( + vault_name=vault.name, + resource_group_name=vault.id.split("/")[4], + policy_name=policy_id.split("/")[-1], + ) + backup_policies_dict[policy_id] = BackupPolicy( + id=policy.id, + name=policy.name, + retention_days=getattr( + getattr( + getattr( + getattr( + getattr(policy, "properties", None), + "retention_policy", + None, + ), + "daily_schedule", + None, + ), + "retention_duration", + None, + ), + "count", + None, + ), + ) + except Exception as error: + logger.error( + f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return backup_policies_dict diff --git a/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/__init__.py b/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.metadata.json b/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.metadata.json new file mode 100644 index 0000000000..60b498ba17 --- /dev/null +++ b/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "azure", + "CheckID": "vm_sufficient_daily_backup_retention_period", + "CheckTitle": "Ensure there is a sufficient daily backup retention period configured for Azure virtual machines.", + "CheckType": [], + "ServiceName": "vm", + "SubServiceName": "", + "ResourceIdTemplate": "", + "Severity": "medium", + "ResourceType": "Microsoft.Compute/virtualMachines", + "Description": "Ensure there is a sufficient daily backup retention period configured for Azure virtual machines.", + "Risk": "Having an optimal daily backup retention period for your Azure virtual machines will enforce your backup strategy to follow the best practices as specified in the compliance regulations promoted by your organization. Retaining VM backups for a longer period of time will allow you to handle more efficiently your data restoration process in the event of a failure.", + "RelatedUrl": "https://docs.microsoft.com/en-us/azure/backup/backup-azure-vms-introduction", + "Remediation": { + "Code": { + "CLI": "", + "NativeIaC": "", + "Other": "https://www.trendmicro.com/cloudoneconformity/knowledge-base/azure/VirtualMachines/sufficient-backup-retention-period.html", + "Terraform": "" + }, + "Recommendation": { + "Text": "Set the daily backup retention period for each VM's backup policy to meet or exceed your organization's minimum requirement.", + "Url": "https://docs.microsoft.com/en-us/azure/backup/backup-azure-vms-introduction" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.py b/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.py new file mode 100644 index 0000000000..221df85351 --- /dev/null +++ b/prowler/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period.py @@ -0,0 +1,51 @@ +from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType + +from prowler.lib.check.models import Check, Check_Report_Azure +from prowler.providers.azure.services.recovery.recovery_client import recovery_client +from prowler.providers.azure.services.vm.vm_client import vm_client + + +class vm_sufficient_daily_backup_retention_period(Check): + """ + Ensure there is a sufficient daily backup retention period configured for Azure virtual machines. + - PASS: The VM has a backup policy with sufficient daily retention period. + - FAIL: The VM does not have a backup policy or the retention period is insufficient. + """ + + def execute(self) -> list[Check_Report_Azure]: + findings = [] + min_retention_days = getattr(vm_client, "audit_config", {}).get( + "vm_backup_min_daily_retention_days", 7 + ) + + for subscription, vms in vm_client.virtual_machines.items(): + vaults = recovery_client.vaults.get(subscription, {}) + for vm in vms.values(): + backup_found = False + retention_days = None + for vault in vaults.values(): + for backup_item in vault.backup_protected_items.values(): + if ( + backup_item.workload_type == DataSourceType.VM + and backup_item.name.split(";")[-1] == vm.resource_name + ): + backup_found = True + policy_id = backup_item.backup_policy_id + if policy_id and policy_id in vault.backup_policies: + retention_days = vault.backup_policies[ + policy_id + ].retention_days + break + if backup_found: + break + if backup_found and retention_days: + report = Check_Report_Azure(metadata=self.metadata(), resource=vm) + report.subscription = subscription + if retention_days >= min_retention_days: + report.status = "PASS" + report.status_extended = f"VM {vm.resource_name} in subscription {subscription} has a daily backup retention period of {retention_days} days (minimum required: {min_retention_days})." + else: + report.status = "FAIL" + report.status_extended = f"VM {vm.resource_name} in subscription {subscription} has insufficient daily backup retention period of {retention_days} days (minimum required: {min_retention_days})." + findings.append(report) + return findings diff --git a/tests/providers/azure/azure_provider_test.py b/tests/providers/azure/azure_provider_test.py index 820ea8785f..5796b15ada 100644 --- a/tests/providers/azure/azure_provider_test.py +++ b/tests/providers/azure/azure_provider_test.py @@ -85,6 +85,7 @@ class TestAzureProvider: "python_latest_version": "3.12", "java_latest_version": "17", "recommended_minimal_tls_versions": ["1.2", "1.3"], + "vm_backup_min_daily_retention_days": 7, "desired_vm_sku_sizes": [ "Standard_A8_v2", "Standard_DS3_v2", diff --git a/tests/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period_test.py b/tests/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period_test.py new file mode 100644 index 0000000000..b43b75548a --- /dev/null +++ b/tests/providers/azure/services/vm/vm_sufficient_daily_backup_retention_period/vm_sufficient_daily_backup_retention_period_test.py @@ -0,0 +1,323 @@ +from unittest import mock +from uuid import uuid4 + +from tests.providers.azure.azure_fixtures import ( + AZURE_SUBSCRIPTION_ID, + set_mocked_azure_provider, +) + + +class Test_vm_sufficient_daily_backup_retention_period: + def test_no_subscriptions(self): + vm_client = mock.MagicMock() + recovery_client = mock.MagicMock() + vm_client.virtual_machines = {} + recovery_client.vaults = {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.recovery_client", + new=recovery_client, + ), + ): + from prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period import ( + vm_sufficient_daily_backup_retention_period, + ) + + check = vm_sufficient_daily_backup_retention_period() + result = check.execute() + assert len(result) == 0 + + def test_no_vms(self): + vm_client = mock.MagicMock() + recovery_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {}} + recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {}} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.recovery_client", + new=recovery_client, + ), + ): + from prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period import ( + vm_sufficient_daily_backup_retention_period, + ) + + check = vm_sufficient_daily_backup_retention_period() + result = check.execute() + assert len(result) == 0 + + def test_vm_with_sufficient_retention(self): + from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType + + from prowler.providers.azure.services.recovery.recovery_service import ( + BackupItem, + BackupPolicy, + BackupVault, + ) + from prowler.providers.azure.services.vm.vm_service import ( + ManagedDiskParameters, + OSDisk, + StorageProfile, + VirtualMachine, + ) + + vm_id = str(uuid4()) + vm_name = "VMTest" + vault_id = str(uuid4()) + policy_id = str(uuid4()) + retention_days = 14 + min_retention_days = 7 + + vm = VirtualMachine( + resource_id=vm_id, + resource_name=vm_name, + location="eastus", + security_profile=None, + extensions=[], + storage_profile=StorageProfile( + os_disk=OSDisk( + name="os_disk_name", + operating_system_type="Linux", + managed_disk=ManagedDiskParameters(id="managed_disk_id"), + ), + data_disks=[], + ), + ) + backup_item = BackupItem( + id=str(uuid4()), + name=f"someprefix;{vm_name}", + workload_type=DataSourceType.VM, + backup_policy_id=policy_id, + ) + backup_policy = BackupPolicy( + id=policy_id, + name="policy1", + retention_days=retention_days, + ) + vault = BackupVault( + id=vault_id, + name="vault1", + location="eastus", + backup_protected_items={backup_item.id: backup_item}, + backup_policies={policy_id: backup_policy}, + ) + vm_client = mock.MagicMock() + recovery_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}} + recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {vault_id: vault}} + vm_client.audit_config = { + "vm_backup_min_daily_retention_days": min_retention_days + } + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider( + audit_config=vm_client.audit_config + ), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.recovery_client", + new=recovery_client, + ), + ): + from prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period import ( + vm_sufficient_daily_backup_retention_period, + ) + + check = vm_sufficient_daily_backup_retention_period() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == vm_name + assert result[0].resource_id == vm_id + assert ( + f"has a daily backup retention period of {retention_days} days" + in result[0].status_extended + ) + + def test_vm_with_insufficient_retention(self): + from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType + + from prowler.providers.azure.services.recovery.recovery_service import ( + BackupItem, + BackupPolicy, + BackupVault, + ) + from prowler.providers.azure.services.vm.vm_service import ( + ManagedDiskParameters, + OSDisk, + StorageProfile, + VirtualMachine, + ) + + vm_id = str(uuid4()) + vm_name = "VMTest" + vault_id = str(uuid4()) + policy_id = str(uuid4()) + retention_days = 3 + min_retention_days = 7 + + vm = VirtualMachine( + resource_id=vm_id, + resource_name=vm_name, + location="eastus", + security_profile=None, + extensions=[], + storage_profile=StorageProfile( + os_disk=OSDisk( + name="os_disk_name", + operating_system_type="Linux", + managed_disk=ManagedDiskParameters(id="managed_disk_id"), + ), + data_disks=[], + ), + ) + backup_item = BackupItem( + id=str(uuid4()), + name=f"someprefix;{vm_name}", + workload_type=DataSourceType.VM, + backup_policy_id=policy_id, + ) + backup_policy = BackupPolicy( + id=policy_id, + name="policy1", + retention_days=retention_days, + ) + vault = BackupVault( + id=vault_id, + name="vault1", + location="eastus", + backup_protected_items={backup_item.id: backup_item}, + backup_policies={policy_id: backup_policy}, + ) + vm_client = mock.MagicMock() + recovery_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}} + recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {vault_id: vault}} + vm_client.audit_config = { + "vm_backup_min_daily_retention_days": min_retention_days + } + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider( + audit_config=vm_client.audit_config + ), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.recovery_client", + new=recovery_client, + ), + ): + from prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period import ( + vm_sufficient_daily_backup_retention_period, + ) + + check = vm_sufficient_daily_backup_retention_period() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == vm_name + assert result[0].resource_id == vm_id + assert ( + f"has insufficient daily backup retention period of {retention_days} days" + in result[0].status_extended + ) + + def test_vm_with_no_backup_policy(self): + from azure.mgmt.recoveryservicesbackup.activestamp.models import DataSourceType + + from prowler.providers.azure.services.recovery.recovery_service import ( + BackupItem, + BackupVault, + ) + from prowler.providers.azure.services.vm.vm_service import ( + ManagedDiskParameters, + OSDisk, + StorageProfile, + VirtualMachine, + ) + + vm_id = str(uuid4()) + vm_name = "VMTest" + vault_id = str(uuid4()) + + vm = VirtualMachine( + resource_id=vm_id, + resource_name=vm_name, + location="eastus", + security_profile=None, + extensions=[], + storage_profile=StorageProfile( + os_disk=OSDisk( + name="os_disk_name", + operating_system_type="Linux", + managed_disk=ManagedDiskParameters(id="managed_disk_id"), + ), + data_disks=[], + ), + ) + backup_item = BackupItem( + id=str(uuid4()), + name=f"someprefix;{vm_name}", + workload_type=DataSourceType.VM, + backup_policy_id=None, + ) + vault = BackupVault( + id=vault_id, + name="vault1", + location="eastus", + backup_protected_items={backup_item.id: backup_item}, + backup_policies={}, + ) + vm_client = mock.MagicMock() + recovery_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}} + recovery_client.vaults = {AZURE_SUBSCRIPTION_ID: {vault_id: vault}} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period.recovery_client", + new=recovery_client, + ), + ): + from prowler.providers.azure.services.vm.vm_sufficient_daily_backup_retention_period.vm_sufficient_daily_backup_retention_period import ( + vm_sufficient_daily_backup_retention_period, + ) + + check = vm_sufficient_daily_backup_retention_period() + result = check.execute() + assert len(result) == 0 From 8b3b9ffd99be310214b5a9ee23347cd796efbe47 Mon Sep 17 00:00:00 2001 From: Prowler Bot Date: Mon, 11 Aug 2025 12:00:02 +0200 Subject: [PATCH 08/30] chore(regions_update): Changes in regions for AWS services (#8499) Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com> --- prowler/providers/aws/aws_regions_by_service.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/prowler/providers/aws/aws_regions_by_service.json b/prowler/providers/aws/aws_regions_by_service.json index 1c2bbd2647..416d2ef8d5 100644 --- a/prowler/providers/aws/aws_regions_by_service.json +++ b/prowler/providers/aws/aws_regions_by_service.json @@ -4269,15 +4269,18 @@ "ap-southeast-1", "ap-southeast-2", "ap-southeast-3", + "ap-southeast-4", "ca-central-1", "ca-west-1", "eu-central-1", + "eu-central-2", "eu-north-1", "eu-south-1", "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3", + "il-central-1", "me-central-1", "me-south-1", "sa-east-1", @@ -5705,12 +5708,15 @@ "ap-south-1", "ap-southeast-1", "ap-southeast-2", + "ap-southeast-5", "ca-central-1", "eu-central-1", "eu-north-1", + "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3", + "me-central-1", "me-south-1", "sa-east-1", "us-east-1", @@ -5916,9 +5922,11 @@ "ap-south-1", "ap-southeast-1", "ap-southeast-2", + "ap-southeast-5", "ca-central-1", "eu-central-1", "eu-north-1", + "eu-south-2", "eu-west-1", "eu-west-2", "eu-west-3", @@ -6580,6 +6588,7 @@ "aws": [ "af-south-1", "ap-east-1", + "ap-east-2", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", @@ -6673,6 +6682,7 @@ "aws": [ "af-south-1", "ap-east-1", + "ap-east-2", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", @@ -9914,6 +9924,7 @@ "aws": [ "af-south-1", "ap-east-1", + "ap-east-2", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", From 5842f2df37a59f8fd8681266bcdadc95e0f70953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20De=20la=20Torre=20Vico?= Date: Mon, 11 Aug 2025 13:12:36 +0200 Subject: [PATCH 09/30] feat(azure/vm): add new check `vm_jit_access_enabled` (#8202) Co-authored-by: MrCloudSec --- prowler/CHANGELOG.md | 1 + .../services/defender/defender_service.py | 46 +++ .../vm/vm_jit_access_enabled/__init__.py | 0 .../vm_jit_access_enabled.metadata.json | 30 ++ .../vm_jit_access_enabled.py | 33 ++ .../defender/defender_service_test.py | 28 ++ .../vm_jit_access_enabled_test.py | 290 ++++++++++++++++++ 7 files changed, 428 insertions(+) create mode 100644 prowler/providers/azure/services/vm/vm_jit_access_enabled/__init__.py create mode 100644 prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.metadata.json create mode 100644 prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.py create mode 100644 tests/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled_test.py diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 76dc4976d1..ea4866f306 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Added - Certificate authentication for M365 provider [(#8404)](https://github.com/prowler-cloud/prowler/pull/8404) - `vm_sufficient_daily_backup_retention_period` check for Azure provider [(#8200)](https://github.com/prowler-cloud/prowler/pull/8200) +- `vm_jit_access_enabled` check for Azure provider [(#8202)](https://github.com/prowler-cloud/prowler/pull/8202) ### Changed diff --git a/prowler/providers/azure/services/defender/defender_service.py b/prowler/providers/azure/services/defender/defender_service.py index f39dfdf484..500441cfb9 100644 --- a/prowler/providers/azure/services/defender/defender_service.py +++ b/prowler/providers/azure/services/defender/defender_service.py @@ -25,6 +25,7 @@ class Defender(AzureService): ).token ) self.iot_security_solutions = self._get_iot_security_solutions() + self.jit_policies = self._get_jit_policies() def _get_pricings(self): logger.info("Defender - Getting pricings...") @@ -246,6 +247,44 @@ class Defender(AzureService): ) return iot_security_solutions + def _get_jit_policies(self) -> dict[str, dict]: + """ + Get all JIT policies for all subscriptions. + + Returns: + A dictionary of JIT policies for each subscription. The format will be: + { + "subscription_name": { + "jit_policy_id": JITPolicy + } + } + """ + logger.info("Defender - Getting JIT policies...") + jit_policies = {} + for subscription_name, client in self.clients.items(): + try: + jit_policies[subscription_name] = {} + policies = client.jit_network_access_policies.list() + for policy in policies: + vm_ids = set() + for vm in getattr(policy, "virtual_machines", []): + vm_ids.add(vm.id) + jit_policies[subscription_name].update( + { + policy.id: JITPolicy( + id=policy.id, + name=policy.name, + location=getattr(policy, "location", "Global"), + vm_ids=vm_ids, + ), + } + ) + except Exception as error: + logger.error( + f"Subscription name: {subscription_name} -- {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return jit_policies + class Pricing(BaseModel): resource_id: str @@ -317,3 +356,10 @@ class IoTSecuritySolution(BaseModel): resource_id: str name: str status: str + + +class JITPolicy(BaseModel): + id: str + name: str + location: str = "" + vm_ids: list[str] = [] diff --git a/prowler/providers/azure/services/vm/vm_jit_access_enabled/__init__.py b/prowler/providers/azure/services/vm/vm_jit_access_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.metadata.json b/prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.metadata.json new file mode 100644 index 0000000000..df9f7d4d10 --- /dev/null +++ b/prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.metadata.json @@ -0,0 +1,30 @@ +{ + "Provider": "azure", + "CheckID": "vm_jit_access_enabled", + "CheckTitle": "Enable Just-In-Time Access for Virtual Machines", + "CheckType": [], + "ServiceName": "vm", + "SubServiceName": "", + "ResourceIdTemplate": "/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}", + "Severity": "high", + "ResourceType": "Microsoft.Compute/virtualMachines", + "Description": "Ensure that Microsoft Azure virtual machines are configured to use Just-in-Time (JIT) access.", + "Risk": "Without JIT access, management ports such as 22 (SSH) and 3389 (RDP) may be exposed, increasing the risk of brute-force and DDoS attacks.", + "RelatedUrl": "https://docs.microsoft.com/en-us/azure/security-center/security-center-just-in-time?tabs=jit-config-asc%2Cjit-request-asc", + "Remediation": { + "Code": { + "CLI": "az security jit-policy list --query '[*].virtualMachines[*].id | []'", + "NativeIaC": "", + "Other": "", + "Terraform": "" + }, + "Recommendation": { + "Text": "Enable Just-in-Time (JIT) network access for your Microsoft Azure virtual machines using the Azure Portal under Security Center > Just-in-time VM access.", + "Url": "https://docs.microsoft.com/en-us/azure/security-center/security-center-just-in-time?tabs=jit-config-asc%2Cjit-request-asc" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "JIT access can only be enabled via the Azure Portal. Ensure Security Center standard pricing tier for servers is enabled." +} diff --git a/prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.py b/prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.py new file mode 100644 index 0000000000..9434608454 --- /dev/null +++ b/prowler/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled.py @@ -0,0 +1,33 @@ +from prowler.lib.check.models import Check, Check_Report_Azure +from prowler.providers.azure.services.defender.defender_client import defender_client +from prowler.providers.azure.services.vm.vm_client import vm_client + + +class vm_jit_access_enabled(Check): + """ + Ensure that Microsoft Azure virtual machines are configured to use Just-in-Time (JIT) access. + + This check evaluates whether JIT access is enabled for each VM to reduce the attack surface. + - PASS: VM has JIT access enabled. + - FAIL: VM does not have JIT access enabled. + """ + + def execute(self): + findings = [] + jit_enabled_vms = set() + for subscription_name, vms in vm_client.virtual_machines.items(): + for jit_policy in defender_client.jit_policies[subscription_name].values(): + jit_enabled_vms.update(jit_policy.vm_ids) + for vm in vms.values(): + report = Check_Report_Azure(metadata=self.metadata(), resource=vm) + report.subscription = subscription_name + if vm.resource_id.lower() in { + vm_id.lower() for vm_id in jit_enabled_vms + }: + report.status = "PASS" + report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} has JIT (Just-in-Time) access enabled." + else: + report.status = "FAIL" + report.status_extended = f"VM {vm.resource_name} in subscription {subscription_name} does not have JIT (Just-in-Time) access enabled." + findings.append(report) + return findings diff --git a/tests/providers/azure/services/defender/defender_service_test.py b/tests/providers/azure/services/defender/defender_service_test.py index 20156640ee..c3189a8e20 100644 --- a/tests/providers/azure/services/defender/defender_service_test.py +++ b/tests/providers/azure/services/defender/defender_service_test.py @@ -6,6 +6,7 @@ from prowler.providers.azure.services.defender.defender_service import ( AutoProvisioningSetting, Defender, IoTSecuritySolution, + JITPolicy, Pricing, SecurityContactConfiguration, Setting, @@ -103,6 +104,19 @@ def mock_defender_get_iot_security_solutions(_): } +def mock_defender_get_jit_policies(_): + return { + AZURE_SUBSCRIPTION_ID: { + "policy-1": JITPolicy( + id="policy-1", + name="JITPolicy1", + location="eastus", + vm_ids=["vm-1", "vm-2"], + ) + } + } + + @patch( "prowler.providers.azure.services.defender.defender_service.Defender._get_pricings", new=mock_defender_get_pricings, @@ -127,6 +141,10 @@ def mock_defender_get_iot_security_solutions(_): "prowler.providers.azure.services.defender.defender_service.Defender._get_iot_security_solutions", new=mock_defender_get_iot_security_solutions, ) +@patch( + "prowler.providers.azure.services.defender.defender_service.Defender._get_jit_policies", + new=mock_defender_get_jit_policies, +) class Test_Defender_Service: def test_get_client(self): defender = Defender(set_mocked_azure_provider()) @@ -255,3 +273,13 @@ class Test_Defender_Service: ].status == "Enabled" ) + + def test_get_jit_policies(self): + defender = Defender(set_mocked_azure_provider()) + assert AZURE_SUBSCRIPTION_ID in defender.jit_policies + assert "policy-1" in defender.jit_policies[AZURE_SUBSCRIPTION_ID] + policy1 = defender.jit_policies[AZURE_SUBSCRIPTION_ID]["policy-1"] + assert policy1.id == "policy-1" + assert policy1.name == "JITPolicy1" + assert policy1.location == "eastus" + assert set(policy1.vm_ids) == {"vm-1", "vm-2"} diff --git a/tests/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled_test.py b/tests/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled_test.py new file mode 100644 index 0000000000..03991f8049 --- /dev/null +++ b/tests/providers/azure/services/vm/vm_jit_access_enabled/vm_jit_access_enabled_test.py @@ -0,0 +1,290 @@ +from unittest import mock +from uuid import uuid4 + +from prowler.providers.azure.services.defender.defender_service import JITPolicy +from prowler.providers.azure.services.vm.vm_service import VirtualMachine +from tests.providers.azure.azure_fixtures import ( + AZURE_SUBSCRIPTION_ID, + set_mocked_azure_provider, +) + + +class Test_vm_jit_access_enabled: + def test_no_subscriptions(self): + vm_client = mock.MagicMock() + vm_client.virtual_machines = {} + defender_client = mock.MagicMock() + defender_client.jit_policies = {} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled import ( + vm_jit_access_enabled, + ) + + check = vm_jit_access_enabled() + result = check.execute() + assert result == [] + + def test_no_vms(self): + vm_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {}} + defender_client = mock.MagicMock() + defender_client.jit_policies = {AZURE_SUBSCRIPTION_ID: {}} + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled import ( + vm_jit_access_enabled, + ) + + check = vm_jit_access_enabled() + result = check.execute() + assert result == [] + + def test_vm_with_jit_enabled(self): + vm_id = str(uuid4()) + vm_name = "TestVM" + vm_location = "eastus" + vm = VirtualMachine( + resource_id=vm_id, + resource_name=vm_name, + location=vm_location, + security_profile=None, + extensions=[], + storage_profile=None, + ) + vm_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}} + defender_client = mock.MagicMock() + jit_policy = JITPolicy( + id="policy1", + name="JITPolicy1", + location="eastus", + vm_ids={vm_id}, + ) + defender_client.jit_policies = { + AZURE_SUBSCRIPTION_ID: {jit_policy.id: jit_policy} + } + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled import ( + vm_jit_access_enabled, + ) + + check = vm_jit_access_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_id == vm_id + assert result[0].resource_name == vm_name + assert "has JIT (Just-in-Time) access enabled" in result[0].status_extended + + def test_vm_with_jit_disabled(self): + vm_id = str(uuid4()) + vm_name = "TestVM" + vm_location = "eastus" + vm = VirtualMachine( + resource_id=vm_id, + resource_name=vm_name, + location=vm_location, + security_profile=None, + extensions=[], + storage_profile=None, + ) + vm_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {vm_id: vm}} + defender_client = mock.MagicMock() + # JIT policy does not include this VM + jit_policy = JITPolicy( + id="policy1", + name="JITPolicy1", + location="eastus", + vm_ids={"some-other-id"}, + ) + defender_client.jit_policies = { + AZURE_SUBSCRIPTION_ID: {jit_policy.id: jit_policy} + } + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled import ( + vm_jit_access_enabled, + ) + + check = vm_jit_access_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_id == vm_id + assert result[0].resource_name == vm_name + assert ( + "does not have JIT (Just-in-Time) access enabled" + in result[0].status_extended + ) + + def test_vm_id_case_insensitivity(self): + vm_id = str(uuid4()) + vm_name = "TestVM" + vm_location = "eastus" + upper_vm_id = vm_id.upper() + vm = VirtualMachine( + resource_id=upper_vm_id, + resource_name=vm_name, + location=vm_location, + security_profile=None, + extensions=[], + storage_profile=None, + ) + vm_client = mock.MagicMock() + vm_client.virtual_machines = {AZURE_SUBSCRIPTION_ID: {upper_vm_id: vm}} + defender_client = mock.MagicMock() + jit_policy = JITPolicy( + id="policy1", + name="JITPolicy1", + location="eastus", + vm_ids={vm_id.lower()}, + ) + defender_client.jit_policies = { + AZURE_SUBSCRIPTION_ID: {jit_policy.id: jit_policy} + } + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled import ( + vm_jit_access_enabled, + ) + + check = vm_jit_access_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].resource_id == upper_vm_id + assert "has JIT (Just-in-Time) access enabled" in result[0].status_extended + + def test_multiple_vms_and_policies(self): + vm_id_1 = str(uuid4()) + vm_id_2 = str(uuid4()) + vm1 = VirtualMachine( + resource_id=vm_id_1, + resource_name="VM1", + location="eastus", + security_profile=None, + extensions=[], + storage_profile=None, + ) + vm2 = VirtualMachine( + resource_id=vm_id_2, + resource_name="VM2", + location="eastus", + security_profile=None, + extensions=[], + storage_profile=None, + ) + vm_client = mock.MagicMock() + vm_client.virtual_machines = { + AZURE_SUBSCRIPTION_ID: {vm_id_1: vm1, vm_id_2: vm2} + } + defender_client = mock.MagicMock() + jit_policy_1 = JITPolicy( + id="policy1", + name="JITPolicy1", + location="eastus", + vm_ids={vm_id_1}, + ) + jit_policy_2 = JITPolicy( + id="policy2", + name="JITPolicy2", + location="eastus", + vm_ids=set(), + ) + defender_client.jit_policies = { + AZURE_SUBSCRIPTION_ID: { + jit_policy_1.id: jit_policy_1, + jit_policy_2.id: jit_policy_2, + } + } + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.vm_client", + new=vm_client, + ), + mock.patch( + "prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled.defender_client", + new=defender_client, + ), + ): + from prowler.providers.azure.services.vm.vm_jit_access_enabled.vm_jit_access_enabled import ( + vm_jit_access_enabled, + ) + + check = vm_jit_access_enabled() + result = check.execute() + assert len(result) == 2 + for r in result: + if r.resource_id == vm_id_1: + assert r.status == "PASS" + elif r.resource_id == vm_id_2: + assert r.status == "FAIL" From 10e38ca4076c51a913e18ccba241f5b8b9ac5847 Mon Sep 17 00:00:00 2001 From: Daniel Barranquero <74871504+danibarranqueroo@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:16:08 +0200 Subject: [PATCH 10/30] fix: missing `resource_name` in GCP and Azure Defender checks (#8352) --- prowler/CHANGELOG.md | 1 + prowler/lib/check/models.py | 4 +- ...mail_configured_with_a_security_contact.py | 5 ++ ..._path_notifications_properly_configured.py | 5 ++ ...r_ensure_notify_alerts_severity_is_high.py | 5 ++ ...defender_ensure_notify_emails_to_owners.py | 8 ++- prowler/providers/gcp/gcp_provider.py | 22 +++++++- .../iam_no_service_roles_at_project_level.py | 3 +- ...for_audit_configuration_changes_enabled.py | 1 + ...t_for_bucket_permission_changes_enabled.py | 1 + ...d_alert_for_custom_role_changes_enabled.py | 1 + ...t_for_project_ownership_changes_enabled.py | 1 + ..._instance_configuration_changes_enabled.py | 1 + ...t_for_vpc_firewall_rule_changes_enabled.py | 1 + ...d_alert_for_vpc_network_changes_enabled.py | 1 + ...t_for_vpc_network_route_changes_enabled.py | 1 + .../logging_sink_created.py | 5 ++ .../compute_project_os_login_enabled_test.py | 4 +- ...am_account_access_approval_enabled_test.py | 54 +++++++++++++++++++ .../iam_audit_logs_enabled_test.py | 4 +- ..._no_service_roles_at_project_level_test.py | 4 +- ...e_kms_enforce_separation_of_duties_test.py | 4 +- ...le_sa_enforce_separation_of_duties_test.py | 4 +- ...udit_configuration_changes_enabled_test.py | 2 +- ..._bucket_permission_changes_enabled_test.py | 2 +- ...rt_for_custom_role_changes_enabled_test.py | 2 +- ..._project_ownership_changes_enabled_test.py | 2 +- ...ance_configuration_changes_enabled_test.py | 2 +- ..._vpc_firewall_rule_changes_enabled_test.py | 2 +- ...rt_for_vpc_network_changes_enabled_test.py | 2 +- ..._vpc_network_route_changes_enabled_test.py | 2 +- .../logging_sink_created_test.py | 2 +- 32 files changed, 131 insertions(+), 27 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index ea4866f306..8a9f4c47c9 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ### Fixed - Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495) +- Add explicit resource name to GCP and Azure Defender checks [(#8352)](https://github.com/prowler-cloud/prowler/pull/8352) - Validation errors in Azure and M365 providers [(#8353)](https://github.com/prowler-cloud/prowler/pull/8353) --- diff --git a/prowler/lib/check/models.py b/prowler/lib/check/models.py index aa24834b89..1c2dd44533 100644 --- a/prowler/lib/check/models.py +++ b/prowler/lib/check/models.py @@ -550,9 +550,7 @@ class Check_Report_GCP(Check_Report): or "" ) self.resource_name = ( - resource_name - or getattr(resource, "name", "") - or getattr(resource, "id", "") + resource_name or getattr(resource, "name", "") or "GCP Project" ) self.project_id = project_id or getattr(resource, "project_id", "") self.location = ( diff --git a/prowler/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact.py b/prowler/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact.py index 8c69f4437a..06cb1f06d2 100644 --- a/prowler/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact.py +++ b/prowler/providers/azure/services/defender/defender_additional_email_configured_with_a_security_contact/defender_additional_email_configured_with_a_security_contact.py @@ -14,6 +14,11 @@ class defender_additional_email_configured_with_a_security_contact(Check): report = Check_Report_Azure( metadata=self.metadata(), resource=contact_configuration ) + report.resource_name = ( + contact_configuration.name + if contact_configuration.name + else "Security Contact" + ) report.subscription = subscription_name if len(contact_configuration.emails) > 0: diff --git a/prowler/providers/azure/services/defender/defender_attack_path_notifications_properly_configured/defender_attack_path_notifications_properly_configured.py b/prowler/providers/azure/services/defender/defender_attack_path_notifications_properly_configured/defender_attack_path_notifications_properly_configured.py index aeacaacac4..8a9935457d 100644 --- a/prowler/providers/azure/services/defender/defender_attack_path_notifications_properly_configured/defender_attack_path_notifications_properly_configured.py +++ b/prowler/providers/azure/services/defender/defender_attack_path_notifications_properly_configured/defender_attack_path_notifications_properly_configured.py @@ -31,6 +31,11 @@ class defender_attack_path_notifications_properly_configured(Check): report = Check_Report_Azure( metadata=self.metadata(), resource=contact_configuration ) + report.resource_name = ( + contact_configuration.name + if contact_configuration.name + else "Security Contact" + ) report.subscription = subscription_name actual_risk_level = getattr( contact_configuration, "attack_path_minimal_risk_level", None diff --git a/prowler/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high.py b/prowler/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high.py index e0ad128e05..d01fec8966 100644 --- a/prowler/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high.py +++ b/prowler/providers/azure/services/defender/defender_ensure_notify_alerts_severity_is_high/defender_ensure_notify_alerts_severity_is_high.py @@ -14,6 +14,11 @@ class defender_ensure_notify_alerts_severity_is_high(Check): report = Check_Report_Azure( metadata=self.metadata(), resource=contact_configuration ) + report.resource_name = ( + contact_configuration.name + if contact_configuration.name + else "Security Contact" + ) report.subscription = subscription_name report.status = "FAIL" report.status_extended = f"Notifications are not enabled for alerts with a minimum severity of high or lower in subscription {subscription_name}." diff --git a/prowler/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners.py b/prowler/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners.py index ce041464b4..ed16c609c3 100644 --- a/prowler/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners.py +++ b/prowler/providers/azure/services/defender/defender_ensure_notify_emails_to_owners/defender_ensure_notify_emails_to_owners.py @@ -12,7 +12,13 @@ class defender_ensure_notify_emails_to_owners(Check): ) in defender_client.security_contact_configurations.items(): for contact_configuration in security_contact_configurations.values(): report = Check_Report_Azure( - metadata=self.metadata(), resource=contact_configuration + metadata=self.metadata(), + resource=contact_configuration, + ) + report.resource_name = ( + contact_configuration.name + if contact_configuration.name + else "Security Contact" ) report.subscription = subscription_name if ( diff --git a/prowler/providers/gcp/gcp_provider.py b/prowler/providers/gcp/gcp_provider.py index 55351b7db3..7cdbba4401 100644 --- a/prowler/providers/gcp/gcp_provider.py +++ b/prowler/providers/gcp/gcp_provider.py @@ -659,6 +659,9 @@ class GcpProvider(Provider): if asset["resource"]["data"].get("name") else project_id ) + # Handle empty or null project names + if not project_name or project_name.strip() == "": + project_name = "GCP Project" gcp_project = GCPProject( number=project_number, id=project_id, @@ -717,6 +720,9 @@ class GcpProvider(Provider): if project.get("name") else project_id ) + # Handle empty or null project names + if not project_name or project_name.strip() == "": + project_name = "GCP Project" project_id = project["projectId"] gcp_project = GCPProject( number=project_number, @@ -757,9 +763,15 @@ class GcpProvider(Provider): # If no projects were able to be accessed via API, add them manually if provided by the user in arguments if project_ids: for input_project in project_ids: + # Handle empty or null project names + project_name = ( + input_project + if input_project and input_project.strip() != "" + else "GCP Project" + ) projects[input_project] = GCPProject( id=input_project, - name=input_project, + name=project_name, number=0, labels={}, lifecycle_state="ACTIVE", @@ -768,9 +780,15 @@ class GcpProvider(Provider): elif credentials_file: with open(credentials_file, "r", encoding="utf-8") as file: project_id = json.load(file)["project_id"] + # Handle empty or null project names + project_name = ( + project_id + if project_id and project_id.strip() != "" + else "GCP Project" + ) projects[project_id] = GCPProject( id=project_id, - name=project_id, + name=project_name, number=0, labels={}, lifecycle_state="ACTIVE", diff --git a/prowler/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level.py b/prowler/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level.py index c10c5e1088..b26841260d 100644 --- a/prowler/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level.py +++ b/prowler/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level.py @@ -13,7 +13,7 @@ class iam_no_service_roles_at_project_level(Check): metadata=self.metadata(), resource=binding, resource_id=binding.role, - resource_name=binding.role, + resource_name=binding.role if binding.role else "Service Role", location=cloudresourcemanager_client.region, ) if binding.role in [ @@ -31,7 +31,6 @@ class iam_no_service_roles_at_project_level(Check): metadata=self.metadata(), resource=cloudresourcemanager_client.projects[project], project_id=project, - resource_name=project, location=cloudresourcemanager_client.region, ) report.status = "PASS" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled.py index 394f6db170..fd48f9dd4b 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled.py @@ -20,6 +20,7 @@ class logging_log_metric_filter_and_alert_for_audit_configuration_changes_enable metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled.py index ee854778f1..db9ea7e95e 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled.py @@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled( metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled.py index b579a776d9..13a2d45737 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled.py @@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_custom_role_changes_enabled(Check) metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled.py index 840f8f0af5..e56feb3318 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled.py @@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled( metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled.py index 1d9b84f2c6..5e37003409 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled.py @@ -17,6 +17,7 @@ class logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled.py index d05b755838..754f651d4d 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled.py @@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled( metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled.py index 1985e73103..5073b59879 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled.py @@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled(Check) metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled.py b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled.py index aa518eb077..9b78bc314a 100644 --- a/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled.py +++ b/prowler/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled.py @@ -18,6 +18,7 @@ class logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled( metadata=self.metadata(), resource=metric, location=logging_client.region, + resource_name=metric.name if metric.name else "Log Metric Filter", ) projects_with_metric.add(metric.project_id) report.status = "FAIL" diff --git a/prowler/providers/gcp/services/logging/logging_sink_created/logging_sink_created.py b/prowler/providers/gcp/services/logging/logging_sink_created/logging_sink_created.py index d180a211ca..a72d45e07e 100644 --- a/prowler/providers/gcp/services/logging/logging_sink_created/logging_sink_created.py +++ b/prowler/providers/gcp/services/logging/logging_sink_created/logging_sink_created.py @@ -26,6 +26,11 @@ class logging_sink_created(Check): metadata=self.metadata(), resource=projects_with_logging_sink[project], location=logging_client.region, + resource_name=( + projects_with_logging_sink[project].name + if projects_with_logging_sink[project].name + else "Logging Sink" + ), ) report.status = "PASS" report.status_extended = f"Sink {projects_with_logging_sink[project].name} is enabled exporting copies of all the log entries in project {project}." diff --git a/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py b/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py index 0dcacf5513..51654533b6 100644 --- a/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py +++ b/tests/providers/gcp/services/compute/compute_project_os_login_enabled/compute_project_os_login_enabled_test.py @@ -175,7 +175,7 @@ class Test_compute_project_os_login_enabled: result[0].status_extended, ) assert result[0].resource_id == project.id - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].location == "global" assert result[0].project_id == GCP_PROJECT_ID @@ -225,6 +225,6 @@ class Test_compute_project_os_login_enabled: result[0].status_extended, ) assert result[0].resource_id == project.id - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].location == "global" assert result[0].project_id == GCP_PROJECT_ID diff --git a/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py b/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py index 395cffb6f0..fab9264535 100644 --- a/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py +++ b/tests/providers/gcp/services/iam/iam_account_access_approval_enabled/iam_account_access_approval_enabled_test.py @@ -44,6 +44,7 @@ class Test_iam_account_access_approval_enabled: result[0].status_extended, ) assert result[0].resource_id == GCP_PROJECT_ID + assert result[0].resource_name == "test" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == "global" @@ -95,5 +96,58 @@ class Test_iam_account_access_approval_enabled: result[0].status_extended, ) assert result[0].resource_id == GCP_PROJECT_ID + assert result[0].resource_name == "test" + assert result[0].project_id == GCP_PROJECT_ID + assert result[0].location == "global" + + def test_iam_project_with_settings_empty_project_name(self): + cloudresourcemanager_client = mock.MagicMock() + accessapproval_client = mock.MagicMock() + accessapproval_client.project_ids = [GCP_PROJECT_ID] + accessapproval_client.region = "global" + accessapproval_client.projects = { + GCP_PROJECT_ID: GCPProject( + id=GCP_PROJECT_ID, + number="123456789012", + name="", + labels={}, + lifecycle_state="ACTIVE", + ) + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_gcp_provider(), + ), + mock.patch( + "prowler.providers.gcp.services.iam.iam_account_access_approval_enabled.iam_account_access_approval_enabled.accessapproval_client", + new=accessapproval_client, + ), + mock.patch( + "prowler.providers.gcp.services.iam.iam_service.cloudresourcemanager_client", + new=cloudresourcemanager_client, + ), + ): + from prowler.providers.gcp.services.iam.iam_service import Setting + + accessapproval_client.settings = { + GCP_PROJECT_ID: Setting(name="test", project_id=GCP_PROJECT_ID) + } + + from prowler.providers.gcp.services.iam.iam_account_access_approval_enabled.iam_account_access_approval_enabled import ( + iam_account_access_approval_enabled, + ) + + check = iam_account_access_approval_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert search( + "has Access Approval enabled", + result[0].status_extended, + ) + assert result[0].resource_id == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == "global" diff --git a/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py b/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py index df1185cac3..c5a773f127 100644 --- a/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py +++ b/tests/providers/gcp/services/iam/iam_audit_logs_enabled/iam_audit_logs_enabled_test.py @@ -176,7 +176,7 @@ class Test_iam_audit_logs_enabled: r.status_extended, ) assert r.resource_id == GCP_PROJECT_ID - assert r.resource_name == GCP_PROJECT_ID + assert r.resource_name == "GCP Project" assert r.project_id == GCP_PROJECT_ID assert r.location == cloudresourcemanager_client.region @@ -226,6 +226,6 @@ class Test_iam_audit_logs_enabled: r.status_extended, ) assert r.resource_id == GCP_PROJECT_ID - assert r.resource_name == GCP_PROJECT_ID + assert r.resource_name == "GCP Project" assert r.project_id == GCP_PROJECT_ID assert r.location == cloudresourcemanager_client.region diff --git a/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py b/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py index 66744d7ef6..45bbdd4b74 100644 --- a/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py +++ b/tests/providers/gcp/services/iam/iam_no_service_roles_at_project_level/iam_no_service_roles_at_project_level_test.py @@ -113,7 +113,7 @@ class Test_iam_no_service_roles_at_project_level: result[0].status_extended, ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "test" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == cloudresourcemanager_client.region @@ -255,6 +255,6 @@ class Test_iam_no_service_roles_at_project_level: result[0].status_extended, ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == cloudresourcemanager_client.region diff --git a/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py b/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py index 95948eb8a6..87efc77174 100644 --- a/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py +++ b/tests/providers/gcp/services/iam/iam_role_kms_enforce_separation_of_duties/iam_role_kms_enforce_separation_of_duties_test.py @@ -213,7 +213,7 @@ class Test_iam_role_kms_enforce_separation_of_duties: r.status_extended, ) assert r.resource_id == GCP_PROJECT_ID - assert r.resource_name == GCP_PROJECT_ID + assert r.resource_name == "GCP Project" assert r.project_id == GCP_PROJECT_ID assert r.location == cloudresourcemanager_client.region @@ -277,6 +277,6 @@ class Test_iam_role_kms_enforce_separation_of_duties: r.status_extended, ) assert r.resource_id == GCP_PROJECT_ID - assert r.resource_name == GCP_PROJECT_ID + assert r.resource_name == "GCP Project" assert r.project_id == GCP_PROJECT_ID assert r.location == cloudresourcemanager_client.region diff --git a/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py b/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py index 5672fc78ad..a15ade396c 100644 --- a/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py +++ b/tests/providers/gcp/services/iam/iam_role_sa_enforce_separation_of_duties/iam_role_sa_enforce_separation_of_duties_test.py @@ -213,7 +213,7 @@ class Test_iam_role_sa_enforce_separation_of_duties: r.status_extended, ) assert r.resource_id == GCP_PROJECT_ID - assert r.resource_name == GCP_PROJECT_ID + assert r.resource_name == "GCP Project" assert r.project_id == GCP_PROJECT_ID assert r.location == cloudresourcemanager_client.region @@ -277,6 +277,6 @@ class Test_iam_role_sa_enforce_separation_of_duties: r.status_extended, ) assert r.resource_id == GCP_PROJECT_ID - assert r.resource_name == GCP_PROJECT_ID + assert r.resource_name == "GCP Project" assert r.project_id == GCP_PROJECT_ID assert r.location == cloudresourcemanager_client.region diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled_test.py index 99fbd43d5e..a38f97d81c 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_audit_configuration_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_audit_configuration_changes_e == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled_test.py index 3faf9c6309..371168fc28 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled/logging_log_metric_filter_and_alert_for_bucket_permission_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_bucket_permission_changes_ena == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled_test.py index fe4ca5e344..4ec94be657 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled/logging_log_metric_filter_and_alert_for_custom_role_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_custom_role_changes_enabled: == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled_test.py index a3279bca0d..4732becb7f 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled/logging_log_metric_filter_and_alert_for_project_ownership_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_project_ownership_changes_ena == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled_test.py index 18562913de..1a8a1d0da3 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled/logging_log_metric_filter_and_alert_for_sql_instance_configuration_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_sql_instance_configuration_ch == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled_test.py index ce773d041d..a9460e6b46 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_vpc_firewall_rule_changes_ena == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled_test.py index e97aba2ec3..9c59d56a81 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_vpc_network_changes_enabled: == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled_test.py b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled_test.py index 1f413a03f2..254c41bb5f 100644 --- a/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled_test.py +++ b/tests/providers/gcp/services/logging/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled/logging_log_metric_filter_and_alert_for_vpc_network_route_changes_enabled_test.py @@ -141,7 +141,7 @@ class Test_logging_log_metric_filter_and_alert_for_vpc_network_route_changes_ena == f"There are no log metric filters or alerts associated in project {GCP_PROJECT_ID}." ) assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION diff --git a/tests/providers/gcp/services/logging/logging_sink_created/logging_sink_created_test.py b/tests/providers/gcp/services/logging/logging_sink_created/logging_sink_created_test.py index f13b19d0cf..a2bab6e5cd 100644 --- a/tests/providers/gcp/services/logging/logging_sink_created/logging_sink_created_test.py +++ b/tests/providers/gcp/services/logging/logging_sink_created/logging_sink_created_test.py @@ -204,7 +204,7 @@ class Test_logging_sink_created: assert len(result) == 1 assert result[0].status == "FAIL" assert result[0].resource_id == GCP_PROJECT_ID - assert result[0].resource_name == GCP_PROJECT_ID + assert result[0].resource_name == "GCP Project" assert result[0].project_id == GCP_PROJECT_ID assert result[0].location == GCP_EU1_LOCATION assert ( From 1562b77581e3bc2e24f61b3ea425b458e4a754e4 Mon Sep 17 00:00:00 2001 From: sumit-tft <70506234+sumit-tft@users.noreply.github.com> Date: Tue, 12 Aug 2025 15:01:45 +0530 Subject: [PATCH 11/30] =?UTF-8?q?fix(ui):=20=20redirection=20after=20delet?= =?UTF-8?q?ing=20providers=20group=20and=20improve=20erro=E2=80=A6=20(#838?= =?UTF-8?q?9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Pablo Lara --- ui/CHANGELOG.md | 1 + ui/actions/manage-groups/manage-groups.ts | 7 +++++-- ui/components/manage-groups/forms/delete-group-form.tsx | 3 +++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 72c52f4a86..f85ed7a8c8 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -81,6 +81,7 @@ All notable changes to the **Prowler UI** are documented in this file. - Error message when launching a scan if user has no permissions [(#8280)](https://github.com/prowler-cloud/prowler/pull/8280) - Include compliance in the download button tooltip [(#8307)](https://github.com/prowler-cloud/prowler/pull/8307) +- Redirection and error handling issues after deleting a provider groups [(#8389)](https://github.com/prowler-cloud/prowler/pull/8389) --- diff --git a/ui/actions/manage-groups/manage-groups.ts b/ui/actions/manage-groups/manage-groups.ts index f2b1ca7289..3b12f619f9 100644 --- a/ui/actions/manage-groups/manage-groups.ts +++ b/ui/actions/manage-groups/manage-groups.ts @@ -201,7 +201,9 @@ export const deleteProviderGroup = async (formData: FormData) => { const providerGroupId = formData.get("id"); if (!providerGroupId) { - return { error: "Provider Group ID is required" }; + return { + errors: [{ detail: "Provider Group ID is required." }], + }; } const url = new URL(`${apiBaseUrl}/provider-groups/${providerGroupId}`); @@ -233,6 +235,7 @@ export const deleteProviderGroup = async (formData: FormData) => { } catch (error) { // eslint-disable-next-line no-console console.error("Error deleting provider group:", error); - return { error: getErrorMessage(error) }; + const message = await getErrorMessage(error); + return { errors: [{ detail: message }] }; } }; diff --git a/ui/components/manage-groups/forms/delete-group-form.tsx b/ui/components/manage-groups/forms/delete-group-form.tsx index 8d268aa7fc..1d51dcd959 100644 --- a/ui/components/manage-groups/forms/delete-group-form.tsx +++ b/ui/components/manage-groups/forms/delete-group-form.tsx @@ -1,6 +1,7 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; +import { useRouter } from "next/navigation"; import React, { Dispatch, SetStateAction } from "react"; import { useForm } from "react-hook-form"; import * as z from "zod"; @@ -26,6 +27,7 @@ export const DeleteGroupForm = ({ resolver: zodResolver(formSchema), }); const { toast } = useToast(); + const router = useRouter(); const isLoading = form.formState.isSubmitting; async function onSubmitClient(formData: FormData) { @@ -46,6 +48,7 @@ export const DeleteGroupForm = ({ title: "Success!", description: "The provider group was removed successfully.", }); + router.push("/manage-groups"); } setIsOpen(false); // Close the modal on success } From 72b06261dfda20eb360034c3b01e060df849259c Mon Sep 17 00:00:00 2001 From: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> Date: Tue, 12 Aug 2025 12:30:43 +0200 Subject: [PATCH 12/30] fix(storage): fall positives in `storage_geo_redundant_enabled` (#8504) --- prowler/CHANGELOG.md | 1 + .../storage_geo_redundant_enabled.py | 11 +- .../azure/services/storage/storage_service.py | 17 +- .../storage_geo_redundant_enabled_test.py | 341 +++++++++++++++++- .../services/storage/storage_service_test.py | 5 +- 5 files changed, 344 insertions(+), 31 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 8a9f4c47c9..f4e0e6d910 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495) - Add explicit resource name to GCP and Azure Defender checks [(#8352)](https://github.com/prowler-cloud/prowler/pull/8352) - Validation errors in Azure and M365 providers [(#8353)](https://github.com/prowler-cloud/prowler/pull/8353) +- Azure `storage_geo_redundant_enabled` check false positives [(#8504)](https://github.com/prowler-cloud/prowler/pull/8504) --- diff --git a/prowler/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled.py b/prowler/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled.py index 971b440b0e..ee2d49e53d 100644 --- a/prowler/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled.py +++ b/prowler/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled.py @@ -1,6 +1,5 @@ from prowler.lib.check.models import Check, Check_Report_Azure from prowler.providers.azure.services.storage.storage_client import storage_client -from prowler.providers.azure.services.storage.storage_service import ReplicationSettings class storage_geo_redundant_enabled(Check): @@ -27,14 +26,16 @@ class storage_geo_redundant_enabled(Check): report.subscription = subscription if ( - storage_account.replication_settings - == ReplicationSettings.STANDARD_GRS + storage_account.replication_settings == "Standard_GRS" + or storage_account.replication_settings == "Standard_GZRS" + or storage_account.replication_settings == "Standard_RAGRS" + or storage_account.replication_settings == "Standard_RAGZRS" ): report.status = "PASS" - report.status_extended = f"Storage account {storage_account.name} from subscription {subscription} has Geo-redundant storage (GRS) enabled." + report.status_extended = f"Storage account {storage_account.name} from subscription {subscription} has Geo-redundant storage {storage_account.replication_settings} enabled." else: report.status = "FAIL" - report.status_extended = f"Storage account {storage_account.name} from subscription {subscription} does not have Geo-redundant storage (GRS) enabled." + report.status_extended = f"Storage account {storage_account.name} from subscription {subscription} does not have Geo-redundant storage enabled, it has {storage_account.replication_settings} instead." findings.append(report) diff --git a/prowler/providers/azure/services/storage/storage_service.py b/prowler/providers/azure/services/storage/storage_service.py index e93b920380..cd5cd07d98 100644 --- a/prowler/providers/azure/services/storage/storage_service.py +++ b/prowler/providers/azure/services/storage/storage_service.py @@ -1,4 +1,3 @@ -from enum import Enum from typing import Optional from azure.mgmt.storage import StorageManagementClient @@ -35,7 +34,6 @@ class Storage(AzureService): key_expiration_period_in_days = int( storage_account.key_policy.key_expiration_period_in_days ) - replication_settings = ReplicationSettings(storage_account.sku.name) storage_accounts[subscription].append( Account( id=storage_account.id, @@ -84,7 +82,7 @@ class Storage(AzureService): False, ) ), - replication_settings=replication_settings, + replication_settings=storage_account.sku.name, allow_cross_tenant_replication=( True if getattr( @@ -273,17 +271,6 @@ class PrivateEndpointConnection(BaseModel): type: str -class ReplicationSettings(Enum): - STANDARD_LRS = "Standard_LRS" - STANDARD_GRS = "Standard_GRS" - STANDARD_RAGRS = "Standard_RAGRS" - STANDARD_ZRS = "Standard_ZRS" - PREMIUM_LRS = "Premium_LRS" - PREMIUM_ZRS = "Premium_ZRS" - STANDARD_GZRS = "Standard_GZRS" - STANDARD_RAGZRS = "Standard_RAGZRS" - - class SMBProtocolSettings(BaseModel): channel_encryption: list[str] supported_versions: list[str] @@ -310,7 +297,7 @@ class Account(BaseModel): minimum_tls_version: str private_endpoint_connections: list[PrivateEndpointConnection] key_expiration_period_in_days: Optional[int] = None - replication_settings: ReplicationSettings = ReplicationSettings.STANDARD_LRS + replication_settings: str = "Standard_LRS" allow_cross_tenant_replication: bool = True allow_shared_key_access: bool = True blob_properties: Optional[BlobProperties] = None diff --git a/tests/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled_test.py b/tests/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled_test.py index 7ae8dc32eb..cfe2f5a00b 100644 --- a/tests/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled_test.py +++ b/tests/providers/azure/services/storage/storage_geo_redundant_enabled/storage_geo_redundant_enabled_test.py @@ -4,7 +4,6 @@ from uuid import uuid4 from prowler.providers.azure.services.storage.storage_service import ( Account, NetworkRuleSet, - ReplicationSettings, ) from tests.providers.azure.azure_fixtures import ( AZURE_SUBSCRIPTION_ID, @@ -35,10 +34,11 @@ class Test_storage_geo_redundant_enabled: result = check.execute() assert len(result) == 0 - def test_storage_geo_redundant_enabled(self): + def test_storage_account_standard_grs_enabled(self): storage_account_id = str(uuid4()) storage_account_name = "Test Storage Account GRS" storage_client = mock.MagicMock() + replication_setting = "Standard_GRS" storage_client.storage_accounts = { AZURE_SUBSCRIPTION_ID: [ Account( @@ -56,7 +56,7 @@ class Test_storage_geo_redundant_enabled: private_endpoint_connections=[], key_expiration_period_in_days=None, location="westeurope", - replication_settings=ReplicationSettings.STANDARD_GRS, + replication_settings=replication_setting, ) ] } @@ -81,17 +81,18 @@ class Test_storage_geo_redundant_enabled: assert result[0].status == "PASS" assert ( result[0].status_extended - == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} has Geo-redundant storage (GRS) enabled." + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} has Geo-redundant storage {replication_setting} enabled." ) assert result[0].subscription == AZURE_SUBSCRIPTION_ID assert result[0].resource_name == storage_account_name assert result[0].resource_id == storage_account_id assert result[0].location == "westeurope" - def test_storage_account_geo_redundant_disabled(self): + def test_storage_account_standard_ragrs_enabled(self): storage_account_id = str(uuid4()) - storage_account_name = "Test Storage Account LRS" + storage_account_name = "Test Storage Account RAGRS" storage_client = mock.MagicMock() + replication_setting = "Standard_RAGRS" storage_client.storage_accounts = { AZURE_SUBSCRIPTION_ID: [ Account( @@ -109,7 +110,169 @@ class Test_storage_geo_redundant_enabled: private_endpoint_connections=[], key_expiration_period_in_days=None, location="westeurope", - replication_settings=ReplicationSettings.STANDARD_LRS, + replication_settings=replication_setting, + ) + ] + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled.storage_client", + new=storage_client, + ), + ): + from prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled import ( + storage_geo_redundant_enabled, + ) + + check = storage_geo_redundant_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} has Geo-redundant storage {replication_setting} enabled." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == storage_account_name + assert result[0].resource_id == storage_account_id + assert result[0].location == "westeurope" + + def test_storage_account_standard_gzrs_enabled(self): + storage_account_id = str(uuid4()) + storage_account_name = "Test Storage Account GZRS" + storage_client = mock.MagicMock() + replication_setting = "Standard_GZRS" + storage_client.storage_accounts = { + AZURE_SUBSCRIPTION_ID: [ + Account( + id=storage_account_id, + name=storage_account_name, + resouce_group_name="rg", + enable_https_traffic_only=False, + infrastructure_encryption=False, + allow_blob_public_access=False, + network_rule_set=NetworkRuleSet( + bypass="AzureServices", default_action="Allow" + ), + encryption_type="None", + minimum_tls_version="TLS1_2", + private_endpoint_connections=[], + key_expiration_period_in_days=None, + location="westeurope", + replication_settings=replication_setting, + ) + ] + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled.storage_client", + new=storage_client, + ), + ): + from prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled import ( + storage_geo_redundant_enabled, + ) + + check = storage_geo_redundant_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} has Geo-redundant storage {replication_setting} enabled." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == storage_account_name + assert result[0].resource_id == storage_account_id + assert result[0].location == "westeurope" + + def test_storage_account_standard_ragzrs_enabled(self): + storage_account_id = str(uuid4()) + storage_account_name = "Test Storage Account RAGZRS" + storage_client = mock.MagicMock() + replication_setting = "Standard_RAGZRS" + storage_client.storage_accounts = { + AZURE_SUBSCRIPTION_ID: [ + Account( + id=storage_account_id, + name=storage_account_name, + resouce_group_name="rg", + enable_https_traffic_only=False, + infrastructure_encryption=False, + allow_blob_public_access=False, + network_rule_set=NetworkRuleSet( + bypass="AzureServices", default_action="Allow" + ), + encryption_type="None", + minimum_tls_version="TLS1_2", + private_endpoint_connections=[], + key_expiration_period_in_days=None, + location="westeurope", + replication_settings=replication_setting, + ) + ] + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled.storage_client", + new=storage_client, + ), + ): + from prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled import ( + storage_geo_redundant_enabled, + ) + + check = storage_geo_redundant_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert ( + result[0].status_extended + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} has Geo-redundant storage {replication_setting} enabled." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == storage_account_name + assert result[0].resource_id == storage_account_id + assert result[0].location == "westeurope" + + def test_storage_account_standard_lrs_disabled(self): + storage_account_id = str(uuid4()) + storage_account_name = "Test Storage Account LRS" + storage_client = mock.MagicMock() + replication_setting = "Standard_LRS" + storage_client.storage_accounts = { + AZURE_SUBSCRIPTION_ID: [ + Account( + id=storage_account_id, + name=storage_account_name, + resouce_group_name="rg", + enable_https_traffic_only=False, + infrastructure_encryption=False, + allow_blob_public_access=False, + network_rule_set=NetworkRuleSet( + bypass="AzureServices", default_action="Allow" + ), + encryption_type="None", + minimum_tls_version="TLS1_2", + private_endpoint_connections=[], + key_expiration_period_in_days=None, + location="westeurope", + replication_settings=replication_setting, ) ] } @@ -134,7 +297,169 @@ class Test_storage_geo_redundant_enabled: assert result[0].status == "FAIL" assert ( result[0].status_extended - == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} does not have Geo-redundant storage (GRS) enabled." + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} does not have Geo-redundant storage enabled, it has {replication_setting} instead." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == storage_account_name + assert result[0].resource_id == storage_account_id + assert result[0].location == "westeurope" + + def test_storage_account_standard_zrs_disabled(self): + storage_account_id = str(uuid4()) + storage_account_name = "Test Storage Account ZRS" + storage_client = mock.MagicMock() + replication_setting = "Standard_ZRS" + storage_client.storage_accounts = { + AZURE_SUBSCRIPTION_ID: [ + Account( + id=storage_account_id, + name=storage_account_name, + resouce_group_name="rg", + enable_https_traffic_only=False, + infrastructure_encryption=False, + allow_blob_public_access=False, + network_rule_set=NetworkRuleSet( + bypass="AzureServices", default_action="Allow" + ), + encryption_type="None", + minimum_tls_version="TLS1_2", + private_endpoint_connections=[], + key_expiration_period_in_days=None, + location="westeurope", + replication_settings=replication_setting, + ) + ] + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled.storage_client", + new=storage_client, + ), + ): + from prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled import ( + storage_geo_redundant_enabled, + ) + + check = storage_geo_redundant_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} does not have Geo-redundant storage enabled, it has {replication_setting} instead." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == storage_account_name + assert result[0].resource_id == storage_account_id + assert result[0].location == "westeurope" + + def test_storage_account_premium_lrs_disabled(self): + storage_account_id = str(uuid4()) + storage_account_name = "Test Storage Account Premium LRS" + storage_client = mock.MagicMock() + replication_setting = "Premium_LRS" + storage_client.storage_accounts = { + AZURE_SUBSCRIPTION_ID: [ + Account( + id=storage_account_id, + name=storage_account_name, + resouce_group_name="rg", + enable_https_traffic_only=False, + infrastructure_encryption=False, + allow_blob_public_access=False, + network_rule_set=NetworkRuleSet( + bypass="AzureServices", default_action="Allow" + ), + encryption_type="None", + minimum_tls_version="TLS1_2", + private_endpoint_connections=[], + key_expiration_period_in_days=None, + location="westeurope", + replication_settings=replication_setting, + ) + ] + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled.storage_client", + new=storage_client, + ), + ): + from prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled import ( + storage_geo_redundant_enabled, + ) + + check = storage_geo_redundant_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} does not have Geo-redundant storage enabled, it has {replication_setting} instead." + ) + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == storage_account_name + assert result[0].resource_id == storage_account_id + assert result[0].location == "westeurope" + + def test_storage_account_premium_zrs_disabled(self): + storage_account_id = str(uuid4()) + storage_account_name = "Test Storage Account Premium ZRS" + storage_client = mock.MagicMock() + replication_setting = "Premium_ZRS" + storage_client.storage_accounts = { + AZURE_SUBSCRIPTION_ID: [ + Account( + id=storage_account_id, + name=storage_account_name, + resouce_group_name="rg", + enable_https_traffic_only=False, + infrastructure_encryption=False, + allow_blob_public_access=False, + network_rule_set=NetworkRuleSet( + bypass="AzureServices", default_action="Allow" + ), + encryption_type="None", + minimum_tls_version="TLS1_2", + private_endpoint_connections=[], + key_expiration_period_in_days=None, + location="westeurope", + replication_settings=replication_setting, + ) + ] + } + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled.storage_client", + new=storage_client, + ), + ): + from prowler.providers.azure.services.storage.storage_geo_redundant_enabled.storage_geo_redundant_enabled import ( + storage_geo_redundant_enabled, + ) + + check = storage_geo_redundant_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert ( + result[0].status_extended + == f"Storage account {storage_account_name} from subscription {AZURE_SUBSCRIPTION_ID} does not have Geo-redundant storage enabled, it has {replication_setting} instead." ) assert result[0].subscription == AZURE_SUBSCRIPTION_ID assert result[0].resource_name == storage_account_name diff --git a/tests/providers/azure/services/storage/storage_service_test.py b/tests/providers/azure/services/storage/storage_service_test.py index 6eb21052a2..912403a0d3 100644 --- a/tests/providers/azure/services/storage/storage_service_test.py +++ b/tests/providers/azure/services/storage/storage_service_test.py @@ -6,7 +6,6 @@ from prowler.providers.azure.services.storage.storage_service import ( DeleteRetentionPolicy, FileServiceProperties, NetworkRuleSet, - ReplicationSettings, SMBProtocolSettings, Storage, ) @@ -53,7 +52,7 @@ def mock_storage_get_storage_accounts(_): location="westeurope", blob_properties=blob_properties, default_to_entra_authorization=True, - replication_settings=ReplicationSettings.STANDARD_LRS, + replication_settings="Standard_LRS", allow_cross_tenant_replication=True, allow_shared_key_access=True, file_service_properties=file_service_properties, @@ -150,7 +149,7 @@ class Test_Storage_Service: ].default_to_entra_authorization assert ( storage.storage_accounts[AZURE_SUBSCRIPTION_ID][0].replication_settings - == ReplicationSettings.STANDARD_LRS + == "Standard_LRS" ) assert ( storage.storage_accounts[AZURE_SUBSCRIPTION_ID][ From b0c386fc60582973c3e4ba1883fc05c91b2ad526 Mon Sep 17 00:00:00 2001 From: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> Date: Tue, 12 Aug 2025 14:47:17 +0200 Subject: [PATCH 13/30] fix(app): fix false positives in `app_http_logs_enabled` (#8507) Co-authored-by: Sergio Garcia --- prowler/CHANGELOG.md | 1 + .../app_http_logs_enabled.py | 4 + .../app_http_logs_enabled_test.py | 138 ++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index f4e0e6d910..892f06b8f7 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495) - Add explicit resource name to GCP and Azure Defender checks [(#8352)](https://github.com/prowler-cloud/prowler/pull/8352) - Validation errors in Azure and M365 providers [(#8353)](https://github.com/prowler-cloud/prowler/pull/8353) +- Azure `app_http_logs_enabled` check false positives [(#8507)](https://github.com/prowler-cloud/prowler/pull/8507) - Azure `storage_geo_redundant_enabled` check false positives [(#8504)](https://github.com/prowler-cloud/prowler/pull/8504) --- diff --git a/prowler/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled.py b/prowler/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled.py index ea70bb708a..137ec3c494 100644 --- a/prowler/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled.py +++ b/prowler/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled.py @@ -22,6 +22,10 @@ class app_http_logs_enabled(Check): report.status = "PASS" report.status_extended = f"App {app.name} has HTTP Logs enabled in diagnostic setting {diagnostic_setting.name} in subscription {subscription_name}" break + elif log.category_group == "allLogs" and log.enabled: + report.status = "PASS" + report.status_extended = f"App {app.name} has allLogs category group which includes HTTP Logs enabled in diagnostic setting {diagnostic_setting.name} in subscription {subscription_name}" + break findings.append(report) return findings diff --git a/tests/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled_test.py b/tests/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled_test.py index d318175a22..7f24fe6284 100644 --- a/tests/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled_test.py +++ b/tests/providers/azure/services/app/app_http_logs_enabled/app_http_logs_enabled_test.py @@ -136,26 +136,32 @@ class Test_app_http_logs_enabled: logs=[ mock.MagicMock( category="AppServiceHTTPLogs", + category_group=None, enabled=True, ), mock.MagicMock( category="AppServiceConsoleLogs", + category_group=None, enabled=False, ), mock.MagicMock( category="AppServiceAppLogs", + category_group=None, enabled=True, ), mock.MagicMock( category="AppServiceAuditLogs", + category_group=None, enabled=False, ), mock.MagicMock( category="AppServiceIPSecAuditLogs", + category_group=None, enabled=False, ), mock.MagicMock( category="AppServicePlatformLogs", + category_group=None, enabled=False, ), ], @@ -181,26 +187,32 @@ class Test_app_http_logs_enabled: logs=[ mock.MagicMock( category="AppServiceHTTPLogs", + category_group=None, enabled=True, ), mock.MagicMock( category="AppServiceConsoleLogs", + category_group=None, enabled=True, ), mock.MagicMock( category="AppServiceAppLogs", + category_group=None, enabled=True, ), mock.MagicMock( category="AppServiceAuditLogs", + category_group=None, enabled=False, ), mock.MagicMock( category="AppServiceIPSecAuditLogs", + category_group=None, enabled=True, ), mock.MagicMock( category="AppServicePlatformLogs", + category_group=None, enabled=False, ), ], @@ -223,3 +235,129 @@ class Test_app_http_logs_enabled: result[0].status_extended == f"App app_id-2 has HTTP Logs enabled in diagnostic setting name_diagnostic_setting2 in subscription {AZURE_SUBSCRIPTION_ID}" ) + + def test_diagnostic_setting_with_all_logs_category_group(self): + app_client = mock.MagicMock + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.app.app_http_logs_enabled.app_http_logs_enabled.app_client", + new=app_client, + ), + ): + from prowler.providers.azure.services.app.app_http_logs_enabled.app_http_logs_enabled import ( + app_http_logs_enabled, + ) + from prowler.providers.azure.services.app.app_service import WebApp + from prowler.providers.azure.services.monitor.monitor_service import ( + DiagnosticSetting, + ) + + app_client.apps = { + AZURE_SUBSCRIPTION_ID: { + "resource_id3": WebApp( + resource_id="resource_id3", + name="app_id-3", + auth_enabled=True, + configurations=None, + client_cert_mode="Ignore", + https_only=False, + kind="WebApp", + identity=mock.MagicMock, + location="West Europe", + monitor_diagnostic_settings=[ + DiagnosticSetting( + id="id3/id3", + logs=[ + mock.MagicMock( + category=None, + category_group="allLogs", + enabled=True, + ), + ], + storage_account_name="storage_account_name3", + storage_account_id="storage_account_id3", + name="name_diagnostic_setting3", + ), + ], + ), + } + } + check = app_http_logs_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == "app_id-3" + assert result[0].resource_id == "resource_id3" + assert ( + result[0].status_extended + == f"App app_id-3 has allLogs category group which includes HTTP Logs enabled in diagnostic setting name_diagnostic_setting3 in subscription {AZURE_SUBSCRIPTION_ID}" + ) + + def test_diagnostic_setting_with_all_logs_category_group_disabled(self): + app_client = mock.MagicMock + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=set_mocked_azure_provider(), + ), + mock.patch( + "prowler.providers.azure.services.app.app_http_logs_enabled.app_http_logs_enabled.app_client", + new=app_client, + ), + ): + from prowler.providers.azure.services.app.app_http_logs_enabled.app_http_logs_enabled import ( + app_http_logs_enabled, + ) + from prowler.providers.azure.services.app.app_service import WebApp + from prowler.providers.azure.services.monitor.monitor_service import ( + DiagnosticSetting, + ) + + app_client.apps = { + AZURE_SUBSCRIPTION_ID: { + "resource_id4": WebApp( + resource_id="resource_id4", + name="app_id-4", + auth_enabled=True, + configurations=None, + client_cert_mode="Ignore", + https_only=False, + kind="WebApp", + identity=mock.MagicMock, + location="West Europe", + monitor_diagnostic_settings=[ + DiagnosticSetting( + id="id4/id4", + logs=[ + mock.MagicMock( + category=None, + category_group="allLogs", + enabled=False, # Disabled + ), + ], + storage_account_name="storage_account_name4", + storage_account_id="storage_account_id4", + name="name_diagnostic_setting4", + ), + ], + ), + } + } + check = app_http_logs_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].subscription == AZURE_SUBSCRIPTION_ID + assert result[0].resource_name == "app_id-4" + assert result[0].resource_id == "resource_id4" + assert ( + result[0].status_extended + == f"App app_id-4 does not have HTTP Logs enabled in diagnostic setting name_diagnostic_setting4 in subscription {AZURE_SUBSCRIPTION_ID}" + ) From d9f3a6b88e5e8a309b56a78fc85fc3af247badd0 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 12 Aug 2025 17:11:30 +0200 Subject: [PATCH 14/30] docs(github): add Github onboarding documentation (#8510) --- .../github/getting-started-github.md | 57 ++++++++++++++++-- docs/tutorials/img/github-app-credentials.png | Bin 0 -> 100387 bytes docs/tutorials/img/github-auth-methods.png | Bin 0 -> 587923 bytes .../img/github-oauth-credentials.png | Bin 0 -> 98277 bytes docs/tutorials/img/github-pat-credentials.png | Bin 0 -> 90850 bytes docs/tutorials/prowler-app.md | 45 ++++++++++++++ 6 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 docs/tutorials/img/github-app-credentials.png create mode 100644 docs/tutorials/img/github-auth-methods.png create mode 100644 docs/tutorials/img/github-oauth-credentials.png create mode 100644 docs/tutorials/img/github-pat-credentials.png diff --git a/docs/tutorials/github/getting-started-github.md b/docs/tutorials/github/getting-started-github.md index 3515b2ca23..d0190a3adf 100644 --- a/docs/tutorials/github/getting-started-github.md +++ b/docs/tutorials/github/getting-started-github.md @@ -13,7 +13,10 @@ This guide explains how to set up authentication with GitHub for Prowler. The do Personal Access Tokens provide the simplest GitHub authentication method and support individual user authentication or testing scenarios. -#### How to Create a Personal Access Token +???+ warning "Classic Tokens Deprecated" + GitHub has deprecated Personal Access Tokens (classic) in favor of fine-grained Personal Access Tokens. We recommend using fine-grained tokens as they provide better security through more granular permissions and resource-specific access control. + +#### **Option 1: Create a Fine-Grained Personal Access Token (Recommended)** 1. **Navigate to GitHub Settings** - Open [GitHub](https://github.com) and sign in @@ -24,18 +27,62 @@ Personal Access Tokens provide the simplest GitHub authentication method and sup - Scroll down the left sidebar - Click "Developer settings" -3. **Generate New Token** +3. **Generate Fine-Grained Token** + - Click "Personal access tokens" + - Select "Fine-grained tokens" + - Click "Generate new token" + +4. **Configure Token Settings** + - **Token name**: Give your token a descriptive name (e.g., "Prowler Security Scanner") + - **Expiration**: Set an appropriate expiration date (recommended: 90 days or less) + - **Repository access**: Choose "All repositories" or "Only select repositories" based on your needs + +5. **Configure Token Permissions** + To enable Prowler functionality, configure the following permissions: + + **Repository permissions:** + - **Contents**: Read-only access + - **Metadata**: Read-only access + - **Pull requests**: Read-only access + - **Security events**: Read-only access + - **Statuses**: Read-only access + + **Organization permissions:** + - **Members**: Read-only access + + **Account permissions:** + - **Email addresses**: Read-only access + +6. **Copy and Store the Token** + - Copy the generated token immediately (GitHub displays tokens only once) + - Store tokens securely using environment variables + +#### **Option 2: Create a Classic Personal Access Token (Not Recommended)** + +???+ warning "Security Risk" + Classic tokens provide broad permissions that may exceed what Prowler actually needs. Use fine-grained tokens instead for better security. + +1. **Navigate to GitHub Settings** + - Open [GitHub](https://github.com) and sign in + - Click the profile picture in the top right corner + - Select "Settings" from the dropdown menu + +2. **Access Developer Settings** + - Scroll down the left sidebar + - Click "Developer settings" + +3. **Generate Classic Token** - Click "Personal access tokens" - Select "Tokens (classic)" - Click "Generate new token" 4. **Configure Token Permissions** To enable Prowler functionality, configure the following scopes: - - `repo`: Full control of private repositories + - `repo`: Full control of private repositories (includes `repo:status` and `repo:contents`) - `read:org`: Read organization and team membership - `read:user`: Read user profile data - - `read:discussion`: Read discussions - - `read:enterprise`: Read enterprise data (if applicable) + - `security_events`: Access security events (secret scanning and Dependabot alerts) + - `read:enterprise`: Read enterprise data (if using GitHub Enterprise) 5. **Copy and Store the Token** - Copy the generated token immediately (GitHub displays tokens only once) diff --git a/docs/tutorials/img/github-app-credentials.png b/docs/tutorials/img/github-app-credentials.png new file mode 100644 index 0000000000000000000000000000000000000000..1a71db4fbdb43c51afdd910bc994c2c69075129a GIT binary patch literal 100387 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 literal 0 HcmV?d00001 diff --git a/docs/tutorials/img/github-auth-methods.png b/docs/tutorials/img/github-auth-methods.png new file mode 100644 index 0000000000000000000000000000000000000000..17414054aa09e2f23830b5db1a4d6b17dbee7cb4 GIT binary patch literal 587923 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

n_2POS?79$!3cQ=oF;+|1 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�RYFm~NF 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

3Wl%~qv4deZA;h$KF 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¬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 literal 0 HcmV?d00001 diff --git a/docs/tutorials/img/github-oauth-credentials.png b/docs/tutorials/img/github-oauth-credentials.png new file mode 100644 index 0000000000000000000000000000000000000000..5d84c4bf7586f421022eed53362da882663934b1 GIT binary patch literal 98277 zcmd3Og`Gm4(Sru>6`ky18fTO()G) z^1LPx8zv)Dh%uPS&BpGr3KYK^FR*C?b}}Myv$3{ydNHG&IEBV zXJ+N$;bCTBV`gJx1dd>IbhmXfa$~f0B>&$@{yC30*wMtn!p_M8VoUOPUL#|Ovy%WB z*<(Zh{{63?U^k0jE!jH$JuF~=%#S6^tV}G-|DGGD%Kx~RSJA=^Y^^13VFOGL(1sw# zOBVjWj{iR;zgqmQrsl7j+?+hW*Zi&Izctky!46^&8=y%i!CzPA@5;Xy{#}uu`ElgG z&BXtv`LDgeJPRW7Gyi+d1QBCD<5)pK2}8+SIi*-MA>dj18c*Wg8Z%$O(j>5}K6 z9xt@Nszfe4A`PN1Iyy)dgf5N_%Dq_1yU-UqY;hI69EEfer4H&H#Oc0`Sw6vZfw-Ev zY&Cgq-=DX*?{1;0_AB^Sbi^wJa%m1EVG5+U^KkH+V_;E?U&E7-l+|H8u zvr%Ao#PpvX2gcDX0{t8e0SThL`m<4CV0ZJg|MXjW1qI_Hjc34-`5u%X6D6;Tp5g(1F<%a zUh;stE!9utzs3yOhZhf{kxP78xwqJ$dcLnsCD2%d#5F+`X*D<%d6H}Kp4Z6IWOLlt zbh3)ps2DS&6QuFH1%hevv(1&7NTZ%k0I{y~EEWI~Vncef2;FQhY*uYy*V8K9-4WW5mE?qkz*SGC} z&3A-2j?7&duBlk)%9KchLYTf^7w+HWMm7gaW{y32+}?3 z+vmC*{TZGuV&$Oah7Hnz_~Xc)*!`Yg@dZ~YC9MiY_=^A}DQ40!UatuqB#yKT3K@*x z9IR<|trnN}$oPWlQJLK9bHTGO{&*(Dp`Rpq4!oGEC~xBN98uP4HjTt)sZo2UlUWhm zS8YBjirmrFrT2oPkTw~j)~JfkXt|I! z|CFm~b1bQ6SSax+Tr^$9uwK(<1fj)vZv4fL+WYYVq$Fm@YaXwSdh3~by{#bws@|yd zmtj9PkFxGy96v5WCe;oWT5zn1MG=s&h8WWYuh^2Mkb(x{nTmUKUbE8E!3!)jdPif& z^cr|v`ExuEMgwKetA5Wv55pc|M#8Cx!}x+IyS$VR9{7B9eA=&4q)`yIG4z94LUy7? z7f#x1JXeX)ZySBHLa&WoE_LlXOB&F9 z^)^$25Vd>~>i&n_PXiFRJ2IWReb%raU^m>2ffTh&d^@=$&Kd%4C)Gqo1M0TuR5Cw5 zzr^!&yy`p_jX&(i3gwfeFt#B=tB>Nd;W*5nliwO@=85(f(~>F{8Ot!54s9s;bbo@J zM)K5(A(I-3pX58|wPNVva~;0KsVm(cNl-Hz#Vx63Tg$&3nnhBs5+`NcLBtuLuQd4* z-zy70!ybssq<>V0ZK9AVn9y>ADmOyl6DOc!#t3@x@_+(|S+7#7MS8W_P^cXc+SIIYW$&UFo?^s)c=>)x{Gz6&^>^ubso+=r?{0e&EQ#MP|U7 zkUcRwGrf$dIK6G{jn3>l+vUnLJ43vNbYv%NWv^;0l!#OA4b7f-{8(QvyII}cCC4QW zoc|J@bS8NFRD{!cT$)z>W!sX=>Kc~Jd)~ayR^L?TYHi6{+6WjhsYWJlT=o_!nk!~u z*S;qy`3~IOpq;s_XGZhZPRx==vM8A@!8|3-T+w3c>Vn#r&pa+UVCIK3T@Wa4Q)WJA z))pQnWMCZDc8R5CuHcX|;k+KC{Nve3MyP-3RcV*S4;?)km43sZ|6%qd@yGfsqS5U# zm%wL|CcD+DiNbH%4qGLq55?2>!nTFoctDzF6R(cnF!o7CWsvY3tH&AV?flpr z&AE@GOBjR~MHZ`;M6m)48*3bg25gbqp;&)LLH1Bui>7DC2hJj!I^IBhWD}>LjwTpC z1QE{jXj+e33Aw3+y$1R>3c9zK_TUc~usl`f2p6j)tvpR-&t=@eZ*YwGJKptQ7aOeFP+2jUvsFM@7(tmgaE%T$)O(l0Rd zt>*JXv9a|$kz;sv7H~5N-8M-4N#3N@MA5zcq!Ar;eK;tnXF4a;Hjrr&Vu_~v0Fi=0 z+7?Sa>O;A`$7yi7D&7RStJTW7eTX6uAZ65cegD2-WXBsGqSx#c`FZ!U!4^$lw2Mk1 zB}W6l#7?T3!{#}~Ld4yc_tx1Fi(7@h^KdJqjkE(}az)!>e$_F(8k81KTBmUP5eF=BGdJlSUm?Y{ZXLQ!|mS%?-cb23+1Bha&AKs_he z3}|0rV0!i%o!5`-|f zdX9&GPDcbUF`UE|f_=cfUGK7zZdKZ;5UYny8VY}yRvZ_)(1df$Evd5#j-l2VbB=Jg z&C-ga2=xzT(=kCU6TJ8xbBjZunJ~eU-^rBM@DGowBz2lKpU9-Jr5tnWRW^&!sq}oF z`ofUO4wg69;sQ_tf0@BlL<1P!x4QPTg>n!)bu|;ae$c#Hxu&eSE-(VjD&8%{Nm%41!0at}-Vw7~FJ7Xv$Es zB7d%Z`3gOz9n;Vh;ze6mAa$h3>z1@qB-$hGnaCRNXs8FLMLB#(TfKBRw4EbcA7Et0 zVQw|tILujMs_gjHP%1j(^WKB&HS|^Xbni9CQ=ur_f-UlAK}?;gxF3R&{2qR)#0eR^ zPS`wF;c>lJi^JG8S)KdS0TFgXs5gC$SB0mprjPOtZ7ATyy-J@@Zi7^SOHUnw$A_*q8U<`K_z0)`FqFu{RaVAZC^vf~nCABoFs$gT#nS+@VrT z|Mmcw$|RPoXhb}eV@24KkAkY6?#R3Qv1jgGJvNONy6p8-r6>rTBz^Y!Lylj|>ChHs z6V5QQa?U1no5%AI2fvz7pOzq(&a?QUGCvKJ?~I|v=&ihO^4M=&GGj~}?%m@3V?E<0 zTftCLFENuK)UGodrb=f$3NdO6EfaF;IVxPG96XAnc%7z5byMc zJ0G!`OO^DJ>wB;H;(UlYu#(Ya#d>&; z)ny_r>6iryXG1MD1*@K8-d`$(pxCMzPw0Di$M?E{cxS6UrS5DQt=W+sD?nxlKf`d8 z@oR17ZCmE@9IXVHM`offoQ(*k%!Vj$cB757$C58D_U~liqqgp1D_d=D^hJ7JQK(+k zKA3j|YK3jcfCst_PK~yQPzDw(4!Smy^eb6&TEF$nQ7IrS%9%}|pgmpJ#y|Ep;MiuV zhhoyGP2N+{pUm{R?cs(=`sGCdUL=SKnhC+6yQ$x>T3!pM%=4+j>?Zy6=>mH{y4iY*kn-SM?4#EtnJy2Kl6SX4Dg3L{cgEnr=UW<% z(RS;|6^d`NJnnZS`r*yRF4s5Oe5d+pL875oGWx8|Lm^d7QGwWtg7_a{RG6=PR&YET z6ow=Dd{^TQED6ZCfuigl25u_+so}@IcfN4@!@|mk0eJs3)CIgL4?szf`Uc zVtN-$a)_}b{E>83@~Y|!c)d|;V7Fc;FG#^e=KB*DGklI~2xE_S%^Q-``_!EIwvQNz zZ`nJ^S8JSl!qhg)AkWMqknVLM&0jGrvWEZk}l9D3P?ZROV#F-)T$QBDx#(Qp`B!Kp^3} zN6NFs#$heTMCpPN@0xdVnSwPw(^>=Z{mzNK&tCEN4<}h1m+j(Z#@hPU$+A6BV&AwC z9Iw2)aZnxJw;Zd_QR-gB=%*aeu%PRE8Op*rB+z-&y4Dj}wwyF6M%n#lDmxtYz0(A4 z6$&TdNvN03eH2&55HLr~Mn9>G@gO`@V8`#gd{M|M{4)1-f@qRL5>tW~`-)V0!t~Qw`Ss-4|xh{f2AURn)R`zw%q13>(ck48Q zV(Co)%Qp*4TRiKZaU6*nWSU9UXFUAKTg4Z9&Xf3Yj(NK!65@aTaYfMFeZF&<|Ug&xPIS)lJa5v%|WNswU;l0CK; zoY?b@n(OchL@{oC!Ef)jtnP+#*ep684ImQ>g_sm0s z?+-7|?G;P%2O01e(bB2#Hk;vgPxJkMYmmtU1)cD-zc1x~Z3kvTNoZZpR#N?8*8oyR zJQ*kmM6de8w|+#M@InA_bX0Bf>JR7%6ue^r3gF32{||Wt@&SmPRrB5tzYp(m8)O6& zpiB1sAC8CQ7KUb^b2N(Mze6PH1PaI^Vo?4=f5ix20t8i1CZW|IXayLea3D}1flG@2 ze@Ln$%#SokLVQyc{~4kmJWvqMBFgz64onz&m0DN{+sCC;=D$1@Iu(dEduVw06~Npe zB|_eR0jMSnw_e|MJ=qTwvGq+-h}T?#wcnTga9NwX=lS%VdO_ts+sY3m0M~<3e}Q{- zhn)Twz7RGA9obzR?;jQi+pA1g>N#3WHn*zM87Nz-(=+3Z7ob0^7i|7qr!MD}ub-z? zsd^Vrqps+3D1dvwsjKw!1|pPX!*@Q=B^9mrm0;ct34Y~?`1|0RjU1Olxm!1T@Zo(I zM5H2H9Y=rqB3r*~;E^xmao7`|fbL%UclMgAVRX03`(p%akS~i<(*zy$pCMms3GU1( zwBjF^@cSH#+Z@vUoQSkk{hXmUFOwZ8xO(8xLt<6r0 zO8x_Fo$Yc$C#<6sBU^DD$Yiz}jIE$BYInBS)g^YkJ%|n#%RAl}D8{`Ew%RK%e4cQb zCzmRVO31?$P4w;NN0{R%=P!dv!ix@{IroVSh8eH(dC1*u$Rtth+qc`t`zuP8c!sk{ z{8|`AYAwwhLkH9VfQ<2mi|Si|rDp(#VGqz-C>O-fRGP?iKsRi3exbK~aAkSBNYY$LWM7ZjU|% zmtf?4_cb*9nCH&StboT`812>@P3>%{78gdB=D32Ev+?7bd87Q6{Es~E)O>)u!AueD>IE-#ChTa}gH_RL1A8m1e~`t|ifK1EoHd%&06wxD zp42`mLmjx>U8ZL z)=ZV@9HYevSChHYphms4o6{XvlJXZwL}sTC2j=b{%PG4)wfLkL$I%yLc1NI#xg7H4 z_8uLrlIKW&0w1Jl|2<}cnYU1rDh@Z>9=M9=rTyQiUX5g}2OpHu* z(cEzi`eoslu%Ve!R1&E*I1^^beLmq+oj?s6!!8vpWjc?GS_L;2@!Ri2WNatsEEew1 zI13|%Tl=Iq%@Ek?77S}s=(F=?4FWFmYF~DZfrlg%5_A1-KGCgY?zE<3vc;%Xh zn0NY$E^uaQ-?QdZv2xMp)|3F6p+Z|+Z?9%X$AKk?w#IUyLQ1Q!dc`8ej|qOvcj?Z% zbryawu_5>m?y^UFYFt0-Y!}ff94`01)y~~;Sq$h>(nQP7DoaoX6o<0~i;(Cka>cdo zJiGn=^?lV=8>2SJkk1yQ+EkwU+vE(V^%8ARJPxZy6hoEwwxC{%T?fBMbM+RZH*GC+ zURTJlDg9Pf5&lebL-j8H?J9Y%RhD91$N-Rwr zDptsoeLh8Ya($MnEiAfabi2)@JDy2+hO%8QIq49mgz!;9Zn_U3=qByg;ICm~y|xbo z1bT=vYrh#2^qwnbuioXKeO_S^FA?wo@#zWKmW{4kJ7?5c&*zL-Su&Q_?JwZV&#Vc9 z()YEw64iEYMe79=Z?)^J3t?9#t+?WGCc2C~1qBgKuk2hMlW4zf?>0!ES!qn7p}#H) zdCEol42vdUGOO#};qtpZtu}WigJ!cfQpVP+o$n#ApiKH{>j@%h>l5{5{CDi{;w29! z6*o031TW#X3vBlXJcI@Vu*^$Z6p$Sfw z)2{SIZ})}VL&_S>6IU3 zr3uwB_o!c`=RhJ>DlaWIGOzPln;Ny)kjV_U7AR$#^`^-7J~a9TCp{%Yz5y1AJOKoN zv1c#tv%#X`aX4LeP+W8q{TOj~V&EKbAw7Cl`P`$yKUHzz<-_s(vcvI&*5Y|Ct>eaQ zH59EbN!@uOFdM3#JW;e2Ft&S!L5Le)WdL6%y=3>}f%K$g|5{MD#$q#maH`ZqTTZhR z?$aq0`!H`%>UZj$hpP+ZP3OUUSm+(DVgtRNh)goWr=;~B`(|2oMyc3*GtsS?8aAD~ zezj5$f?A=IPiOKjf;gG7ne!!BMH`{>m>Nw7;SA1-=+ zwBp&pNBp7)ZF0%H?#zbic0sa361K9)#t>T(y|?J9S=Xe#_^u1d;yig~U4zAdiPFh? zW82^%E3cj`3hSj>KIwiu*mO;QO8)Ajd)~(2 z;o-97&w8@Y84dfdL&wI9C5{JucN+b9ZdzW}Sy&N@x`rKdik;$4^9^9BFQ?8_8uu42 zQ(Nd8a#{|FYgKv#l$pg#HAmUPWfLu5ywY(QP}oW1Qe8&j$F=V{8hhq{vW$ncc{+>`OseLUL0AvB76S2PE}d!y7ew+y#R% zZR708GgyqE8Rb7c)xydY^faRlNELmDMc_C)aF)2Q>8Am2QMsEM2wh8_i$of8Bs*J0 zFv}(rwWpQqzRug>(uMg}u}G)x5N6)?Fn|XJnXBqkz4W)T1;)@xOdojqg}xVwazPFP zO3;YGtZF5?lAe3Dw1;!*n~ZGyibiW`xo8*}%;dlqI~j~z3N zK_pjA${`Rqc+e6ulv)GN!O1;OBp$=_9F2@23nOGC*!4RCOO|}w{IKebQ4{`-fIg*vw3>DF7 z`-uf-#1rJzAc1Tm3T`$6$KqrE)cuik&qNm86PMrk()Lsefc^-^R~?e;Y{pw42{EfQ z{xY$Ix65`k)2({aj@+foSS?}*`|KHH{<^yC^UVyloIq9`r<scUso%V$+|{%4M=z`)Y4BIum)maZOYw>_KloIb&@@Fp+vg z&abyQh=pTX9|(Uh<-S9JS5E9EUWRh=lZ9)@I$7f#Pvnu$9J~2^wV;9DXy&{XTlaZ8 zjvqE!f;)95X_w{Jp@!z@S#Ts@u2ZO}HUX(T){;h7+MWK3&3(q<>Cy(|)_JbUE_`$3 zZC2r*UmB`8)3!C$w`Ut8e&THtx6x0XC--ZX#vZZ%gL>QXsU9Z}1~ffEklRR?1&g5% z5FV?+uUWC|75H;I#UG69!A0C+hgeXd9Zj>Wp&YE zNQRbW(1SwNNkPo-MMJM{Gv=$7FpV6l;-h91F%pFo5+WT|vgK*ygLcniP_#>JGr?cB z_yOVC_Mnm7Tde75Wu<2>tsW+;sNgkh(C1aJE=>QJsy3>TcwaTqBtL_Tn3@Nh8aIKj zs6!tz+Yl)wW)?*`;6|)@s=!|zQ-G^1PyYHE+PX=zka1oIf+eJkJ)+;OL^?`PI2es}J(((_yk zBi0#>G-4_^7e<-|1G|g=!|NT&1q4+LcwAerw#(8SRR#@F-*WZ5h}M3tYn14>N#+L#gVA+T0)_|a^1gNO%V3&?3q6BMj(8&JCG7Kyg$iXq9rWoS& zbjYECEZF9k`^u!nZ|W*7(Pnv+;I^}Y0RBK~yvGjBNQ zyUw|c1{?F~)w95NQvSF@0z<_x=v72(9tlbQ#QLQ0I20c`E;{?*f2+ny~6y74rWWPn? zn_t0*7QeGQN9BrNM!uCPK&{ZvOFI``F+&vHO@;W5XCS;piH5~cA$hO6i;Z&nHHOW5 zMq%CGUA^-g%8=S%QB^IXJ&c?gdR{HT~e$SNS_)_I7+;#+YRvP#h|I#cL9SyP64 z>vWhJ{^p&Tvol#B^9|ZJeTLJTeYnU3sM37M$DgLY6Ni{K!TmPNH41r&qfF!>7fFYz zvR>OPHIOq-T9sx;u|}-KgPpZxop&eJ z^s~tP>>!@xwrA*YI?Y~X8A2h>ZaSUgL_2}KAnb7ab!U`5C`7ce@0AaQ^0|bJ!=$nB zfxU(3PdED43$DEi6p{w2mOUsLw&x0wlmd`Ha3{_JXp>35R#NB<9&2u<2UeGgw_w>e z>WBH473&_t*_h4GvKkTJ2T6BYQN`?a)h`WglHN~FE14U1J738UV@b$*QS7q}DfzZv zMk9Q4rqXEkfo>k_DdrGCgNtyf|Ha<;alL9ECU*&5!K~38BVVv19YS!Fwj(zkwW~hU z3`$C&ewe4Ng*pw#1@X`*vxyt69HVP{S4OW%x*a(+GUUon=_OpemAa|9U?NE zB?QmAu1fT{^P^RhkmqFtz%Sc(vdiM=`=xxWgRO%U*~a)h_hP+ z`nc8ZT(^(;H6~I1n^ehPbW}ya+d+Qt*2tRKIPbSK_qNJ|h-B7*U~njM#1=zD)J}F= z76RKuo%2&m`pS1LCbPwmic)tzHl4ZZZ8|*BH~zgT_INfSoIakRY@)mPb6;LLy}1*^ zTd?Lcsl5z3hdY>E28;hY@AloK<*t>q-o3O_p^6XfHa z2KC8I@(aRO@tlZdHvRbSX@Q-Xb=JSs`pFA2_H64R$ZX`4nqOXwkLtI;+FN=AKy>8@ zhD*2E-Kj|(V8@Op>6qnZ*!F;~zmiBMV&wKKV#of@(wMP0M?d;np3ss`4G2-R}*=1si)*|P2DbQ5={;=&%7ZGcS@QcUj!LLC9oG%Wvl6L%} z#v$eWCyQP_&+<;*R=}4Z$mvyJ;3tt@p?t|ux{n1Adu=*{g~XGId0{x?dIxhSzEwW! z=kTs=MlCzaEWYLNbzOfly6y5LvIX63j@ubSI`!lH8LpNBrR%92u0`P6zv;YDjRNk{ z{muRawdUrfgHH;BZ*59*%9tiao0b*+Iv$Upue5dwX>R-5vxiZuL?6<5|lV8l5$4mm143F{Gm>}3zD3+vy{yG z&7V%!yVN6{S_%|0e{ga^7HwwX6rRmlF6EYQ3}r~zF1OMHP$yPQ>UITXP>dJE=Pbt*Ea6&(!hCEj-_uQfs`s_`qK7CL@DLxxkFlV!p9*qEuU7 zIaiu41odk0B#G<3@Mfc51u5iZk;;IdSntNw$#x>=cccy7v7PQ;R0!## z5NiV5xE=Na^U^woa5HmiD<9fBOya0sAzmGyjA+Mf4#cWenZ9P`bJ@q)Jr~6vEFkv% zI7-{CS4noYxwcv2uudtIc6focY!>ENo~8wO>~anO{~^~_>F>StbFIGtDT!ge<1?fp zy8GeMqTyjBi$Wn$`~zn(B_mcy+!rKSGAs{w`F(bA)nUs`=M+G>r9D@uQxZpUeD-xe zn;2kTuo>)Ixr%lH&)a-}?>oJ>hYtmwTAyX`X%Q?@^)WcS0bD zFD8`lO386Gs!T(_Jak(O-gGs$tjm;a9sW3!Oi`Ag2*&8@RY?0f8QE&A6M~j1Q!@Yt zBDI>29A=I?)9*otY?i-V%?(vWu9o^$y-JT9g-jz7Z+c7I7680Wm=rBJ~UoMkT*D9Yk{bbqAJ8i z1$n$q1JBneG&+Yr0d%VLJlc!F1MiTH5aQmxb3)I&yO39uYQ?6K=;=o}I@?p);=pqK z+J{(3t;(#w5H?wf1{`Lp+#;)`)nN9%RCS$I=Z;qmwioYW`XwIgj)F`f3^dF;qvSf+ zSRTk%*_sDtO3{|QbPT&-N|`i8!JE(N3k{AMk`V-tn!QA}yl`m?XL4H`Lo*`azWEAa zfvp2@$KX>+uS5oel2HUeCdT}^l0mylGWsq8L!8}=IWat`{QChGQ?k?xu0mQljeF|5 zR>G|ACBYweTGTS7Jz!4wu&_0{ZaoGc7k4&Y52?(wk7fJ4YA+&bu~C zPDI%*t3tW8a+RhC-uVgl)!Bti9HS1EHz5oRf6`CPeEJTr@o}QslwtkFk0$N|1v?+Q zyxI`nn-yExhUp((+gtf12N)4f-^Z-B4GKMsd?Uj^<295tIN2U9DsS=yk5BL@mpic* zX)OsCx=msiOz z2iF7wLb^0UKRgNW!FFpgq*h4BaRanm! z({>4Wh~4z;x-8uiM-1v2xZA~PFLCFV!#Ta-Ya9%_&M#K z6SjCSbz)UH-w?^+nSj5Jb5!XrF5qWm0qVK|seK*XrkXmNxgm+-=zEX(Oic5>y5-X` zV+5|_nqrNZmK(IeHg@ctyMj^u7|eo^zIKRU^=Bgp?5(KPe4*>Z{nJ_Bqrw%p-gvm9 zfyv#Ta>K!~9tY9%kcojDxYdAKWUE}5ZCpyam3{v*{U$&%^E$UB4f7$TtZp@P(G$&L z^m$-5>33PW=mgfflKeG0O?O!PR%E`cz=elv=cGN^dSb8s(HV0{=q?J`vUPpp*fyXZ z?F$M|V!R81V{*)QO3a>`CU5rNR&#%+J@b8;njRfbB~wLbU+aZ3{rOI|ypi)T=?ys% zGz<*PcS~x8OcgSYRQ+BdH}1DqSVU^NbtTg_iMl*hn&l#=&I^GS+HZ3BTk$0(yF%5h zxK_!3j{%b)V%nw9@Of`FOT^&ugV;h?Sh`5uBJ3os2jeIM8r_B7pqtJFr;geTbg9*< zDtW19h4Xlj4yxe||M`DN0gx7ln9&NkXa zOL*~FvVU&m-o7~}u7qd%47>X7FvJLCdPHG1`aw%iqrXPVeLCZ5k8ML4f63PFrT?*R zr<~j`hZ%?fU&H8Pw8A4t6Tt;VrNj!0uihC-a=(B{nq3JJ#al)XkHf4I=k#v^nEP z2z7R@#2;*C=!EWXLxkm%hm$eE)}H8>mJ5}}#jH9AxbdFW0hvn6&B$dojy&d5>3HD{ zgzI_`(3F|WE|;xJRz^n`zY^pwe_vTN^i7)YkX%3rXwT?+VSepn?HAREG!Awh^IhD{ z(oxptOas(QrE^+los_tsgo~;WL(~*@Y;C=W-YFigIoNQY7NM_>SQU%)Mf|lTrdw&0 zJ+>{M1rPo5dBQpnkDvaA3WejzSJ)J^wjzFfj`9DM2GjPZXgLc(&I51T|gvi40e*^?ccvB=GhiR$%4oj2kf?1`Td7FFYe4@%aj! zpr}*jm0l^s9Q&?ATNjr8qu}K=)ffV;$Lam+gQb=VS8^LKO=M{HR0AqG47dpiXk;Od z3Y(KiJtK<&qgjC28VEOUN@h3ld&4>%GL5#rRC8m<@+5qWUnl!1f-uR_$`jG5NQ(gz zvl-ThZ*z`jfg;9yTN*|qtIe?VPL-Y)MBlqvBncT-i<;bi6uZA4oMJWD@8}AtGM;>P zr=dnUQ3ym)KNxUo5sQU$vxC0Hij{bZrk_AxIRw{_#Kvs&4C}-RK~NcW+teLTk?Gqf zZk{3jw(zc`Qv-8`*ZClLFeZwGv!E*$!=bE&E0%gvB^SgbN{ z2vG3e!b@i|)u1xY*Si-izOOPqduFkmADXLV6vW~-<=?Db5ywVCf!vAG>jwwt3zox~ zbWE|k9b-5G*9yRMLSeP`Q#+Z^%Z z+njYzN@W_iyLyPzhi^N~1~vNT&GJW8Z6I<3uc@!L;|OU|fnjU6M4aGC-JC7?M}c36 zC>akzCtoZfx>+C-873u0I7u2>qE2WN0o|~#sa6dg7$!vkC7Pu9gMNm7Vway(/N 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

KYiuH9IzZfc+ZUBiK&0r{wu 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 E4-r=!{Qv*} literal 0 HcmV?d00001 diff --git a/docs/tutorials/prowler-app.md b/docs/tutorials/prowler-app.md index b7eb18e183..85e498aba5 100644 --- a/docs/tutorials/prowler-app.md +++ b/docs/tutorials/prowler-app.md @@ -201,6 +201,51 @@ For full setup instructions and requirements, check the [Microsoft 365 provider Prowler Cloud M365 Credentials +### **Step 4.6: GitHub Credentials** +For GitHub, you must enter your Provider ID (username or organization name) and choose the authentication method you want to use: + +- **Personal Access Token** (Recommended for individual users) +- **OAuth App Token** (For applications requiring user consent) +- **GitHub App** (Recommended for organizations and production use) + +???+ note + For full setup instructions and requirements, check the [GitHub provider requirements](./github/getting-started-github.md). + +GitHub Authentication Methods + +#### **Step 4.6.1: Personal Access Token** + +Personal Access Tokens provide the simplest GitHub authentication method and support individual user authentication or testing scenarios. + +- Select `Personal Access Token` and enter your `Personal Access Token`: + +GitHub Personal Access Token Credentials + +???+ note + For detailed instructions on creating a Personal Access Token and the exact permissions required, check the [GitHub Personal Access Token tutorial](./github/getting-started-github.md#1-personal-access-token-pat). + +#### **Step 4.6.2: OAuth App Token** + +OAuth Apps enable applications to act on behalf of users with explicit consent. + +- Select `OAuth App Token` and enter your `OAuth App Token`: + +GitHub OAuth App Credentials + +???+ note + To create an OAuth App, go to GitHub Settings → Developer settings → OAuth Apps → New OAuth App. You'll need to exchange an authorization code for an access token using the OAuth flow. + +#### **Step 4.6.3: GitHub App** + +GitHub Apps provide the recommended integration method for accessing multiple repositories or organizations. + +- Select `GitHub App` and enter your `GitHub App ID` and `GitHub App Private Key`: + + GitHub App Credentials + +???+ note + To create a GitHub App, go to GitHub Settings → Developer settings → GitHub Apps → New GitHub App. Configure the necessary permissions and generate a private key. Install the app to your account or organization and provide the App ID and private key content. + ## **Step 5: Test Connection** After adding your credentials of your cloud account, click the `Launch` button to verify that Prowler App can successfully connect to your provider: From f5b1532647958d93dbe93d5cab0179dc698be0a9 Mon Sep 17 00:00:00 2001 From: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> Date: Wed, 13 Aug 2025 09:05:09 +0200 Subject: [PATCH 15/30] fix(kafka): false positives in `kafka_cluster_is_public` check (#8514) --- prowler/CHANGELOG.md | 1 + .../kafka_cluster_is_public/kafka_cluster_is_public.py | 6 +++--- .../kafka_cluster_is_public_test.py | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 892f06b8f7..9c8c6e6c44 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -23,6 +23,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Validation errors in Azure and M365 providers [(#8353)](https://github.com/prowler-cloud/prowler/pull/8353) - Azure `app_http_logs_enabled` check false positives [(#8507)](https://github.com/prowler-cloud/prowler/pull/8507) - Azure `storage_geo_redundant_enabled` check false positives [(#8504)](https://github.com/prowler-cloud/prowler/pull/8504) +- AWS `kafka_cluster_is_public` check false positives [(#8514)](https://github.com/prowler-cloud/prowler/pull/8514) --- diff --git a/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py b/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py index 597839978d..426ff04490 100644 --- a/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py +++ b/prowler/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public.py @@ -10,13 +10,13 @@ class kafka_cluster_is_public(Check): report = Check_Report_AWS(metadata=self.metadata(), resource=cluster) report.status = "FAIL" report.status_extended = ( - f"Kafka cluster '{cluster.name}' is publicly accessible." + f"Kafka cluster {cluster.name} is publicly accessible." ) - if cluster.public_access: + if not cluster.public_access: report.status = "PASS" report.status_extended = ( - f"Kafka cluster '{cluster.name}' is not publicly accessible." + f"Kafka cluster {cluster.name} is not publicly accessible." ) findings.append(report) diff --git a/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py b/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py index 5925a435cd..392582b0ee 100644 --- a/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py +++ b/tests/providers/aws/services/kafka/kafka_cluster_is_public/kafka_cluster_is_public_test.py @@ -72,10 +72,10 @@ class Test_kafka_cluster_is_public: result = check.execute() assert len(result) == 1 - assert result[0].status == "FAIL" + assert result[0].status == "PASS" assert ( result[0].status_extended - == "Kafka cluster 'demo-cluster-1' is publicly accessible." + == "Kafka cluster demo-cluster-1 is not publicly accessible." ) assert ( result[0].resource_arn @@ -126,10 +126,10 @@ class Test_kafka_cluster_is_public: result = check.execute() assert len(result) == 1 - assert result[0].status == "PASS" + assert result[0].status == "FAIL" assert ( result[0].status_extended - == "Kafka cluster 'demo-cluster-1' is not publicly accessible." + == "Kafka cluster demo-cluster-1 is publicly accessible." ) assert ( result[0].resource_arn From 0e1578cfbc39ce511aae13f2f9896d99a5acae61 Mon Sep 17 00:00:00 2001 From: Jaen-923 <113357550+Jaen-923@users.noreply.github.com> Date: Wed, 13 Aug 2025 16:08:37 +0900 Subject: [PATCH 16/30] chore(aws): Refine kisa isms-p compliance mapping (#8479) Co-authored-by: ghkim583 <203069125+ghkim583@users.noreply.github.com> --- prowler/CHANGELOG.md | 1 + .../compliance/aws/kisa_isms_p_2023_aws.json | 1229 ++-------------- .../aws/kisa_isms_p_2023_korean_aws.json | 1276 ++--------------- 3 files changed, 240 insertions(+), 2266 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 9c8c6e6c44..e330cfd745 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - `vm_jit_access_enabled` check for Azure provider [(#8202)](https://github.com/prowler-cloud/prowler/pull/8202) ### Changed +- Refine kisa isms-p compliance mapping [(#8479)](https://github.com/prowler-cloud/prowler/pull/8479) ### Fixed diff --git a/prowler/compliance/aws/kisa_isms_p_2023_aws.json b/prowler/compliance/aws/kisa_isms_p_2023_aws.json index 03bd5acaef..bd9b256c37 100644 --- a/prowler/compliance/aws/kisa_isms_p_2023_aws.json +++ b/prowler/compliance/aws/kisa_isms_p_2023_aws.json @@ -206,11 +206,7 @@ "Id": "1.2.1", "Name": "Identification of Information Assets", "Description": "Organizations must establish classification criteria for information assets according to the characteristics of their operations, identify and classify all information assets within the scope of the management system, assess their importance, and maintain an up-to-date list.", - "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "1. Establishment and Operation of the Management System", @@ -403,10 +399,7 @@ "Id": "1.3.3", "Name": "Operation Status Management", "Description": "According to the management system established by the organization, operational activities that must be performed continuously or periodically must be recorded and managed in a way that allows identification and tracking, and management must regularly review the effectiveness of operational activities and manage them accordingly.", - "Checks": [ - "cloudwatch_log_metric_filter_aws_organizations_changes", - "codebuild_project_older_90_days" - ], + "Checks": [], "Attributes": [ { "Domain": "1. Establishment and Operation of the Management System", @@ -574,11 +567,7 @@ "Id": "2.1.2", "Name": "Organization Maintenance", "Description": "Roles and responsibilities related to information protection and personal information protection must be assigned to all members of the organization, and systems must be established for evaluating these activities and for communication between members and departments.", - "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -617,18 +606,13 @@ "Name": "Management of Information Assets", "Description": "The procedures and protection measures for handling information assets according to their purpose and importance must be established and implemented, and the responsibilities for each asset must be clearly defined and managed.", "Checks": [ - "ec2_elastic_ip_unassigned", - "ec2_instance_older_than_specific_days", - "ecr_repositories_lifecycle_policy_enabled", - "neptune_cluster_copy_tags_to_snapshots", + "fsx_file_system_copy_tags_to_backups_enabled", "fsx_file_system_copy_tags_to_volumes_enabled", - "organizations_account_part_of_organizations", - "organizations_delegated_administrators", - "organizations_scp_check_deny_regions", + "neptune_cluster_copy_tags_to_snapshots", "organizations_tags_policies_enabled_and_attached", "rds_cluster_copy_tags_to_snapshots", "rds_instance_copy_tags_to_snapshots", - "resourceexplorer2_indexes_found" + "redshift_cluster_non_default_username" ], "Attributes": [ { @@ -658,10 +642,7 @@ "Id": "2.2.1", "Name": "Designation and Management of Key Personnel", "Description": "Criteria and management plans for key duties, such as handling personal information and important information or accessing key systems, must be established, and the number of key personnel must be minimized and their list kept up-to-date.", - "Checks": [ - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -697,9 +678,7 @@ "Id": "2.2.2", "Name": "Separation of Duties", "Description": "Criteria for the separation of duties must be established and applied to prevent potential harm from the misuse or abuse of authority. If separation of duties is unavoidable, supplementary measures must be established and implemented.", - "Checks": [ - "account_maintain_different_contact_details_to_security_billing_and_operations" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -1201,17 +1180,12 @@ "Checks": [ "accessanalyzer_enabled", "accessanalyzer_enabled_without_findings", - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", "account_security_questions_are_registered_in_the_aws_account", - "apigateway_restapi_authorizers_enabled", - "autoscaling_group_launch_configuration_requires_imdsv2", + "cognito_identity_pool_guest_access_disabled", "cognito_user_pool_deletion_protection_enabled", "cognito_user_pool_self_registration_disabled", - "config_recorder_using_aws_service_role", "ec2_instance_profile_attached", - "eventbridge_schema_registry_cross_account_access", + "iam_avoid_root_usage", "iam_aws_attached_policy_no_administrative_privileges", "iam_customer_attached_policy_no_administrative_privileges", "iam_customer_unattached_policy_no_administrative_privileges", @@ -1221,7 +1195,6 @@ "iam_inline_policy_no_full_access_to_cloudtrail", "iam_inline_policy_no_full_access_to_kms", "iam_no_custom_policy_permissive_role_assumption", - "iam_no_root_access_key", "iam_policy_allows_privilege_escalation", "iam_policy_attached_only_to_group_or_roles", "iam_policy_cloudshell_admin_not_attached", @@ -1232,7 +1205,10 @@ "iam_role_cross_service_confused_deputy_prevention", "iam_securityaudit_role_created", "iam_support_role_created", - "iam_user_administrator_access_policy" + "iam_user_administrator_access_policy", + "rds_cluster_default_admin", + "rds_instance_default_admin", + "redshift_cluster_non_default_database_name" ], "Attributes": [ { @@ -1267,8 +1243,6 @@ "Name": "User Identification", "Description": "User accounts must be assigned unique identifiers that distinguish each user individually, and the use of easily guessable identifiers must be restricted. If the same identifier is shared by multiple users, the reason and justification must be reviewed, supplementary measures such as approval from a responsible party must be established, and accountability must be ensured.", "Checks": [ - "cognito_user_pool_advanced_security_enabled", - "ec2_instance_profile_attached", "efs_access_point_enforce_user_identity" ], "Attributes": [ @@ -1303,15 +1277,14 @@ "Description": "User access to information systems, personal information, and critical information must be secured through safe authentication procedures and, if necessary, enhanced authentication methods. In addition, access control measures such as limiting login attempts and issuing warnings for illegal login attempts must be established and implemented.", "Checks": [ "account_security_questions_are_registered_in_the_aws_account", - "apigateway_restapi_client_certificate_enabled", + "apigateway_restapi_authorizers_enabled", "apigateway_restapi_public_with_authorizer", "apigatewayv2_api_authorizers_enabled", "appstream_fleet_maximum_session_duration", "appstream_fleet_session_disconnect_timeout", "appstream_fleet_session_idle_disconnect_timeout", + "autoscaling_group_launch_configuration_requires_imdsv2", "cloudtrail_bucket_requires_mfa_delete", - "cloudwatch_log_metric_filter_authentication_failures", - "cloudwatch_log_metric_filter_sign_in_without_mfa", "cognito_user_pool_advanced_security_enabled", "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", @@ -1325,24 +1298,16 @@ "elasticache_redis_replication_group_auth_enabled", "iam_administrator_access_with_mfa", "iam_check_saml_providers_sts", - "iam_no_root_access_key", "iam_root_hardware_mfa_enabled", "iam_root_mfa_enabled", - "iam_rotate_access_key_90_days", - "iam_user_accesskey_unused", "iam_user_console_access_unused", "iam_user_hardware_mfa_enabled", "iam_user_mfa_enabled_console_access", - "iam_user_no_setup_initial_access_key", - "iam_user_two_active_access_key", "iam_user_with_temporary_credentials", "neptune_cluster_iam_authentication_enabled", - "opensearch_service_domains_internal_user_database_enabled", "opensearch_service_domains_use_cognito_authentication_for_kibana", - "organizations_account_part_of_organizations", "rds_cluster_iam_authentication_enabled", "rds_instance_iam_authentication_enabled", - "s3_bucket_cross_account_access", "s3_bucket_no_mfa_delete" ], "Attributes": [ @@ -1423,11 +1388,6 @@ "Checks": [ "accessanalyzer_enabled", "accessanalyzer_enabled_without_findings", - "apigateway_restapi_authorizers_enabled", - "cloudwatch_log_metric_filter_root_usage", - "cognito_user_pool_self_registration_disabled", - "config_recorder_using_aws_service_role", - "ecs_task_definitions_no_privileged_containers", "iam_administrator_access_with_mfa", "iam_avoid_root_usage", "iam_aws_attached_policy_no_administrative_privileges", @@ -1445,17 +1405,12 @@ "iam_policy_no_full_access_to_cloudtrail", "iam_policy_no_full_access_to_kms", "iam_role_administratoraccess_policy", - "iam_role_cross_account_readonlyaccess_policy", "iam_root_hardware_mfa_enabled", "iam_root_mfa_enabled", "iam_securityaudit_role_created", "iam_support_role_created", "iam_user_administrator_access_policy", - "organizations_delegated_administrators", - "rds_cluster_default_admin", - "rds_instance_default_admin", - "sagemaker_notebook_instance_root_access_disabled", - "ses_identity_not_publicly_accessible" + "organizations_delegated_administrators" ], "Attributes": [ { @@ -1492,25 +1447,9 @@ "Checks": [ "accessanalyzer_enabled", "accessanalyzer_enabled_without_findings", - "apigateway_restapi_authorizers_enabled", - "appstream_fleet_maximum_session_duration", - "appstream_fleet_session_disconnect_timeout", - "appstream_fleet_session_idle_disconnect_timeout", - "autoscaling_group_launch_configuration_requires_imdsv2", - "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_group_not_publicly_accessible", - "cloudwatch_log_metric_filter_policy_changes", - "cognito_identity_pool_guest_access_disabled", - "cognito_user_pool_advanced_security_enabled", - "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", - "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", - "cognito_user_pool_client_prevent_user_existence_errors", - "cognito_user_pool_client_token_revocation_enabled", - "cognito_user_pool_self_registration_disabled", "config_recorder_using_aws_service_role", "dynamodb_table_cross_account_access", "ec2_instance_internet_facing_with_instance_profile", - "ec2_instance_managed_by_ssm", "ec2_instance_profile_attached", "eventbridge_bus_cross_account_access", "eventbridge_schema_registry_cross_account_access", @@ -1538,7 +1477,6 @@ "s3_bucket_policy_public_write_access", "s3_bucket_public_list_acl", "s3_bucket_public_write_acl", - "ses_identity_not_publicly_accessible", "sns_topics_not_publicly_accessible", "sqs_queues_not_publicly_accessible", "ssm_documents_set_as_public", @@ -1576,27 +1514,22 @@ "Name": "Network Access", "Description": "In order to control unauthorized access to the network, management procedures such as IP management and device authentication must be established and implemented. Network segmentation (DMZ, server farm, DB zone, development zone, etc.) and access controls must be applied according to the business purpose and importance.", "Checks": [ - "apigateway_restapi_authorizers_enabled", - "apigateway_restapi_client_certificate_enabled", "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", "apigateway_restapi_waf_acl_attached", "appstream_fleet_default_internet_access_disabled", "autoscaling_group_launch_configuration_no_public_ip", "awslambda_function_inside_vpc", "awslambda_function_not_publicly_accessible", - "cloudfront_distributions_default_root_object", "cloudfront_distributions_geo_restrictions_enabled", "cloudfront_distributions_s3_origin_access_control", "cloudfront_distributions_using_waf", "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", - "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", - "cloudwatch_log_metric_filter_security_group_changes", + "cloudwatch_log_group_not_publicly_accessible", "cognito_user_pool_waf_acl_attached", + "dms_endpoint_ssl_enabled", "dms_instance_no_public_access", "documentdb_cluster_public_snapshot", - "dynamodb_table_cross_account_access", + "ec2_elastic_ip_shodan", "ec2_instance_internet_facing_with_instance_profile", "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_cifs_exposed_to_internet", @@ -1641,68 +1574,50 @@ "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", "ec2_securitygroup_allow_wide_open_public_ipv4", "ec2_securitygroup_default_restrict_traffic", - "ec2_securitygroup_from_launch_wizard", - "ec2_securitygroup_not_used", - "ec2_securitygroup_with_many_ingress_egress_rules", "ec2_transitgateway_auto_accept_vpc_attachments", "ecr_repositories_not_publicly_accessible", "ecs_service_no_assign_public_ip", "ecs_task_set_no_assign_public_ip", "efs_mount_target_not_publicly_accessible", - "efs_not_publicly_accessible", "eks_cluster_network_policy_enabled", "eks_cluster_not_publicly_accessible", "eks_cluster_private_nodes_enabled", "elasticache_cluster_uses_public_subnet", "elb_internet_facing", "elbv2_internet_facing", - "elbv2_listeners_underneath", "elbv2_waf_acl_attached", "emr_cluster_account_public_block_enabled", "emr_cluster_master_nodes_no_public_ip", "emr_cluster_publicly_accesible", - "eventbridge_bus_exposed", - "glue_data_catalogs_not_publicly_accessible", + "glacier_vaults_policy_public_access", "kafka_cluster_is_public", - "kafka_cluster_unrestricted_access_disabled", "lightsail_database_public", "lightsail_instance_public", - "lightsail_static_ip_unused", - "neptune_cluster_public_snapshot", "neptune_cluster_uses_public_subnet", - "networkfirewall_deletion_protection", - "networkfirewall_in_all_vpc", - "networkfirewall_multi_az", - "networkfirewall_policy_default_action_fragmented_packets", - "networkfirewall_policy_default_action_full_packets", - "networkfirewall_policy_rule_group_associated", "opensearch_service_domains_not_publicly_accessible", - "rds_snapshots_public_access", + "rds_cluster_non_default_port", "rds_instance_inside_vpc", + "rds_instance_no_public_access", + "rds_instance_non_default_port", "redshift_cluster_enhanced_vpc_routing", "redshift_cluster_public_access", "route53_dangling_ip_subdomain_takeover", "s3_access_point_public_access_block", + "s3_account_level_public_access_blocks", + "s3_bucket_level_public_access_block", + "s3_bucket_public_access", + "s3_multi_region_access_point_public_access_block", "sagemaker_models_network_isolation_enabled", "sagemaker_models_vpc_settings_configured", "sagemaker_notebook_instance_vpc_settings_configured", "sagemaker_notebook_instance_without_direct_internet_access_configured", "sagemaker_training_jobs_network_isolation_enabled", "sagemaker_training_jobs_vpc_settings_configured", - "sqs_queues_server_side_encryption_enabled", "vpc_endpoint_connections_trust_boundaries", "vpc_endpoint_for_ec2_enabled", "vpc_peering_routing_tables_with_least_privilege", "vpc_subnet_no_public_ip_by_default", "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", - "waf_global_rule_with_conditions", - "waf_global_rulegroup_not_empty", - "waf_global_webacl_with_rules", - "waf_regional_rule_with_conditions", - "waf_regional_rulegroup_not_empty", - "waf_regional_webacl_with_rules", - "wafv2_webacl_with_rules", "workspaces_vpc_2private_1public_subnets_nat" ], "Attributes": [ @@ -1722,7 +1637,6 @@ ], "AuditEvidence": [ "Network diagram", - "IP management ledger", "Information asset list", "Firewall rules" ], @@ -1741,24 +1655,14 @@ "Name": "Access to Information Systems", "Description": "The users, access restriction methods, and secure access means for accessing information systems such as servers and network systems must be defined and controlled.", "Checks": [ - "apigateway_restapi_client_certificate_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", "apigateway_restapi_waf_acl_attached", - "apigatewayv2_api_authorizers_enabled", "athena_workgroup_enforce_configuration", - "autoscaling_group_launch_configuration_requires_imdsv2", - "awslambda_function_inside_vpc", - "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", - "awslambda_function_not_publicly_accessible", - "cloudfront_distributions_s3_origin_access_control", + "awslambda_function_url_cors_policy", + "awslambda_function_url_public", + "cloudfront_distributions_default_root_object", + "cloudfront_distributions_using_waf", "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_group_not_publicly_accessible", - "cognito_identity_pool_guest_access_disabled", - "cognito_user_pool_client_token_revocation_enabled", - "dms_instance_no_public_access", - "documentdb_cluster_public_snapshot", - "dynamodb_table_cross_account_access", + "cognito_user_pool_waf_acl_attached", "ec2_ami_public", "ec2_ebs_public_snapshot", "ec2_ebs_snapshot_account_block_public_access", @@ -1766,70 +1670,39 @@ "ec2_instance_imdsv2_enabled", "ec2_instance_internet_facing_with_instance_profile", "ec2_instance_managed_by_ssm", - "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_cifs_exposed_to_internet", + "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", + "ec2_instance_port_kafka_exposed_to_internet", + "ec2_instance_port_kerberos_exposed_to_internet", + "ec2_instance_port_ldap_exposed_to_internet", "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", "ec2_instance_port_ssh_exposed_to_internet", "ec2_instance_port_telnet_exposed_to_internet", - "ec2_networkacl_allow_ingress_any_port", - "ec2_networkacl_allow_ingress_tcp_port_22", - "ec2_networkacl_allow_ingress_tcp_port_3389", - "ec2_networkacl_unused", "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", "ec2_securitygroup_allow_ingress_from_internet_to_any_port", "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", - "ecr_repositories_not_publicly_accessible", - "ecs_service_no_assign_public_ip", - "ecs_task_definitions_host_namespace_not_shared", - "ecs_task_definitions_host_networking_mode_users", "ecs_task_definitions_no_privileged_containers", - "ecs_task_set_no_assign_public_ip", "efs_access_point_enforce_root_directory", "efs_access_point_enforce_user_identity", - "efs_mount_target_not_publicly_accessible", "efs_not_publicly_accessible", - "eks_cluster_network_policy_enabled", - "eks_cluster_not_publicly_accessible", - "eks_cluster_private_nodes_enabled", - "elasticache_cluster_uses_public_subnet", - "elasticache_redis_replication_group_auth_enabled", - "emr_cluster_account_public_block_enabled", - "emr_cluster_master_nodes_no_public_ip", - "emr_cluster_publicly_accesible", + "elbv2_waf_acl_attached", + "eventbridge_bus_cross_account_access", "eventbridge_bus_exposed", - "glacier_vaults_policy_public_access", + "eventbridge_schema_registry_cross_account_access", "glue_data_catalogs_not_publicly_accessible", - "guardduty_lambda_protection_enabled", - "guardduty_s3_protection_enabled", "kafka_cluster_is_public", "kafka_cluster_unrestricted_access_disabled", - "lightsail_instance_public", - "lightsail_static_ip_unused", "neptune_cluster_public_snapshot", "opensearch_service_domains_not_publicly_accessible", "opensearch_service_domains_use_cognito_authentication_for_kibana", + "rds_snapshots_public_access", "s3_access_point_public_access_block", "s3_account_level_public_access_blocks", "s3_bucket_acl_prohibited", @@ -1840,7 +1713,10 @@ "s3_bucket_public_list_acl", "s3_bucket_public_write_acl", "s3_multi_region_access_point_public_access_block", - "ssm_documents_set_as_public" + "sagemaker_notebook_instance_root_access_disabled", + "ses_identity_not_publicly_accessible", + "ssm_documents_set_as_public", + "vpc_endpoint_connections_trust_boundaries" ], "Attributes": [ { @@ -1878,24 +1754,8 @@ "Name": "Access to Applications", "Description": "Access rights to applications must be restricted according to the user's tasks and the importance of the accessed information, and criteria should be established to minimize exposure of unnecessary or sensitive information.", "Checks": [ - "apigateway_restapi_authorizers_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", - "apigatewayv2_api_authorizers_enabled", - "awslambda_function_url_cors_policy", - "awslambda_function_url_public", - "cloudfront_distributions_default_root_object", - "codeartifact_packages_external_public_publishing_disabled", - "cognito_user_pool_waf_acl_attached", - "ec2_ami_public", "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ecr_repositories_not_publicly_accessible", - "ecs_task_definitions_host_namespace_not_shared", - "ecs_task_definitions_host_networking_mode_users", - "eks_cluster_network_policy_enabled" + "opensearch_service_domains_use_cognito_authentication_for_kibana" ], "Attributes": [ { @@ -1920,9 +1780,7 @@ "Application session time and concurrent session restriction settings", "Application administrator access log monitoring details", "Information asset list", - "Personal information processing system's personal information viewing and search screens", - "Personal information masking standards", - "Personal information masking application screen" + "Personal information processing system's personal information viewing and search screens" ], "NonComplianceCases": [ "Case 1: There is a flaw in the authorization control function of certain personal information processing screens in the application, allowing users without permission to view personal information.", @@ -1944,7 +1802,6 @@ "dms_endpoint_mongodb_authentication_enabled", "dms_endpoint_neptune_iam_authorization_enabled", "dms_endpoint_ssl_enabled", - "documentdb_cluster_public_snapshot", "dynamodb_table_cross_account_access", "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_memcached_exposed_to_internet", @@ -1954,6 +1811,10 @@ "ec2_instance_port_postgresql_exposed_to_internet", "ec2_instance_port_redis_exposed_to_internet", "ec2_instance_port_sqlserver_exposed_to_internet", + "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", @@ -1961,25 +1822,17 @@ "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", - "guardduty_rds_protection_enabled", + "elasticache_redis_replication_group_auth_enabled", "lightsail_database_public", "neptune_cluster_iam_authentication_enabled", - "neptune_cluster_uses_public_subnet", + "neptune_cluster_public_snapshot", "opensearch_service_domains_internal_user_database_enabled", "rds_cluster_iam_authentication_enabled", "rds_cluster_non_default_port", - "rds_cluster_storage_encrypted", "rds_instance_iam_authentication_enabled", "rds_instance_no_public_access", "rds_instance_non_default_port", - "rds_instance_storage_encrypted", - "rds_instance_transport_encrypted", - "rds_snapshots_public_access", - "redshift_cluster_encrypted_at_rest", "redshift_cluster_enhanced_vpc_routing", - "redshift_cluster_in_transit_encryption_enabled", - "redshift_cluster_non_default_database_name", - "redshift_cluster_non_default_username", "redshift_cluster_public_access" ], "Attributes": [ @@ -2054,7 +1907,6 @@ "appstream_fleet_maximum_session_duration", "appstream_fleet_session_disconnect_timeout", "appstream_fleet_session_idle_disconnect_timeout", - "autoscaling_group_launch_configuration_requires_imdsv2", "ec2_instance_port_cifs_exposed_to_internet", "ec2_instance_port_ftp_exposed_to_internet", "ec2_instance_port_rdp_exposed_to_internet", @@ -2062,12 +1914,13 @@ "ec2_instance_port_telnet_exposed_to_internet", "ec2_networkacl_allow_ingress_tcp_port_22", "ec2_networkacl_allow_ingress_tcp_port_3389", + "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", - "vpc_vpn_connection_tunnels_up", - "workspaces_volume_encryption_enabled", "workspaces_vpc_2private_1public_subnets_nat" ], "Attributes": [ @@ -2082,8 +1935,8 @@ "Are the devices used for remote access to personal information processing systems for management, operation, development, and security purposes designated as management terminals, and are safety measures such as prohibiting unauthorized operations and use for purposes other than those intended being applied?" ], "RelatedRegulations": [ - "Personal Information Protection Act Article 29 (Obligation to Take Safety Measures)", - "Standards for Ensuring the Safety of Personal Information Article 6 (Access Control)" + "Personal Information Protection Act, Article 29 (Obligation to Take Safety Measures)", + "Standards for Ensuring the Safety of Personal Information, Article 6 (Access Control)" ], "AuditEvidence": [ "Remote access application form (e.g., VPN)", @@ -2107,59 +1960,7 @@ "Id": "2.6.7", "Name": "Internet Access Control", "Description": "To prevent information leaks, malware infections, and intrusions into the internal network through the internet, policies must be established and implemented to restrict internet access or services (e.g., P2P, web hard drives, messengers) on key information systems, devices handling sensitive duties, and terminals processing personal information.", - "Checks": [ - "apigateway_restapi_waf_acl_attached", - "appstream_fleet_default_internet_access_disabled", - "autoscaling_group_launch_configuration_no_public_ip", - "awslambda_function_not_publicly_accessible", - "awslambda_function_url_cors_policy", - "awslambda_function_url_public", - "cloudfront_distributions_using_waf", - "dms_instance_no_public_access", - "ec2_elastic_ip_shodan", - "ec2_instance_port_cassandra_exposed_to_internet", - "ec2_instance_port_cifs_exposed_to_internet", - "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", - "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", - "ec2_instance_port_ssh_exposed_to_internet", - "ec2_instance_port_telnet_exposed_to_internet", - "ec2_instance_public_ip", - "ecs_service_no_assign_public_ip", - "elb_internet_facing", - "elbv2_internet_facing", - "emr_cluster_account_public_block_enabled", - "emr_cluster_master_nodes_no_public_ip", - "emr_cluster_publicly_accesible", - "eventbridge_bus_exposed", - "glue_data_catalogs_not_publicly_accessible", - "kafka_cluster_is_public", - "kafka_cluster_unrestricted_access_disabled", - "neptune_cluster_public_snapshot", - "networkfirewall_deletion_protection", - "networkfirewall_in_all_vpc", - "networkfirewall_multi_az", - "opensearch_service_domains_not_publicly_accessible", - "route53_dangling_ip_subdomain_takeover", - "sagemaker_notebook_instance_without_direct_internet_access_configured", - "vpc_endpoint_connections_trust_boundaries", - "vpc_endpoint_for_ec2_enabled", - "vpc_peering_routing_tables_with_least_privilege", - "vpc_subnet_no_public_ip_by_default", - "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", - "workspaces_vpc_2private_1public_subnets_nat" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -2171,8 +1972,8 @@ "Are internet access restrictions being applied in a secure manner for individuals who are required by law to have their internet access restricted?" ], "RelatedRegulations": [ - "Personal Information Protection Act Article 29 (Obligation to Take Safety Measures)", - "Standards for Ensuring the Safety of Personal Information Article 6 (Access Control)" + "Personal Information Protection Act, Article 29 (Obligation to Take Safety Measures)", + "Standards for Ensuring the Safety of Personal Information, Article 6 (Access Control)" ], "AuditEvidence": [ "Policy for blocking non-work-related sites (e.g., P2P) (management screen of non-work-related site blocking system)", @@ -2198,8 +1999,8 @@ "Checks": [ "acm_certificates_expiration_check", "acm_certificates_with_secure_key_algorithms", - "apigateway_restapi_authorizers_enabled", "apigateway_restapi_cache_encrypted", + "apigateway_restapi_client_certificate_enabled", "athena_workgroup_encryption", "awslambda_function_no_secrets_in_code", "awslambda_function_no_secrets_in_variables", @@ -2211,7 +2012,6 @@ "cloudfront_distributions_https_sni_enabled", "cloudfront_distributions_origin_traffic_encrypted", "cloudfront_distributions_using_deprecated_ssl_protocols", - "cloudwatch_log_group_no_secrets_in_logs", "codebuild_project_no_secrets_in_variables", "codebuild_project_s3_logs_encrypted", "codebuild_project_source_repo_url_no_sensitive_credentials", @@ -2229,7 +2029,6 @@ "ec2_launch_template_no_secrets", "ecs_task_definitions_no_environment_secrets", "efs_encryption_at_rest_enabled", - "eks_cluster_kms_cmk_encryption_in_secrets_enabled", "elasticache_redis_cluster_in_transit_encryption_enabled", "elasticache_redis_cluster_rest_encryption_enabled", "elb_insecure_ssl_ciphers", @@ -2248,7 +2047,7 @@ "glue_etl_jobs_cloudwatch_logs_encryption_enabled", "glue_etl_jobs_job_bookmark_encryption_enabled", "glue_ml_transform_encrypted_at_rest", - "kafka_cluster_encryption_at_rest_uses_cmk", + "iam_no_expired_server_certificates_stored", "kafka_cluster_in_transit_encryption_enabled", "kafka_cluster_mutual_tls_authentication_enabled", "kafka_connector_in_transit_encryption_enabled", @@ -2259,6 +2058,7 @@ "opensearch_service_domains_https_communications_enforced", "opensearch_service_domains_node_to_node_encryption_enabled", "rds_cluster_storage_encrypted", + "rds_instance_certificate_expiration", "rds_instance_storage_encrypted", "rds_instance_transport_encrypted", "rds_snapshots_encrypted", @@ -2268,11 +2068,11 @@ "s3_bucket_secure_transport_policy", "sagemaker_notebook_instance_encryption_enabled", "sagemaker_training_jobs_intercontainer_encryption_enabled", - "sagemaker_training_jobs_volume_and_output_encryption_enabled", "sns_subscription_not_using_http_endpoints", "sqs_queues_server_side_encryption_enabled", "ssm_document_secrets", - "transfer_server_in_transit_encryption_enabled" + "transfer_server_in_transit_encryption_enabled", + "workspaces_volume_encryption_enabled" ], "Attributes": [ { @@ -2308,40 +2108,30 @@ "Name": "Cryptographic Key Management", "Description": "Establish and implement management procedures for the secure generation, use, storage, distribution, and destruction of cryptographic keys, and prepare recovery methods if necessary.", "Checks": [ - "acm_certificates_expiration_check", - "acm_certificates_transparency_logs_enabled", - "athena_workgroup_encryption", "backup_vaults_encrypted", "bedrock_model_invocation_logs_encryption_enabled", - "cloudfront_distributions_custom_ssl_certificate", - "cloudfront_distributions_https_enabled", - "cloudfront_distributions_https_sni_enabled", - "cloudfront_distributions_origin_traffic_encrypted", - "cloudfront_distributions_using_deprecated_ssl_protocols", "cloudtrail_kms_encryption_enabled", "cloudwatch_log_group_kms_encryption_enabled", - "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", - "dms_endpoint_ssl_enabled", "dynamodb_tables_kms_cmk_encryption_enabled", "eks_cluster_kms_cmk_encryption_in_secrets_enabled", - "iam_no_expired_server_certificates_stored", + "iam_no_root_access_key", "iam_rotate_access_key_90_days", "iam_user_accesskey_unused", "iam_user_no_setup_initial_access_key", "iam_user_two_active_access_key", + "kafka_cluster_encryption_at_rest_uses_cmk", "kms_cmk_are_used", "kms_cmk_not_deleted_unintentionally", "kms_cmk_rotation_enabled", "kms_key_not_publicly_accessible", - "rds_instance_certificate_expiration", "s3_bucket_kms_encryption", + "sagemaker_training_jobs_volume_and_output_encryption_enabled", "secretsmanager_automatic_rotation_enabled", "secretsmanager_not_publicly_accessible", "secretsmanager_secret_rotated_periodically", "secretsmanager_secret_unused", "sns_topics_kms_encryption_at_rest_enabled", - "storagegateway_fileshare_encryption_enabled", - "workspaces_volume_encryption_enabled" + "storagegateway_fileshare_encryption_enabled" ], "Attributes": [ { @@ -2498,10 +2288,7 @@ "Id": "2.8.5", "Name": "Source Program Management", "Description": "Source programs must be managed so that only authorized users can access them, and it is a principle that they should not be stored in the operational environment.", - "Checks": [ - "codeartifact_packages_external_public_publishing_disabled", - "ecr_repositories_tag_immutability" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -2587,7 +2374,6 @@ "Name": "Performance and Fault Management", "Description": "To ensure the availability of information systems, performance and capacity requirements must be defined, and the status must be continuously monitored. Procedures for detecting, recording, analyzing, recovering, and reporting in response to faults must be established and managed effectively.", "Checks": [ - "acm_certificates_expiration_check", "apigateway_restapi_tracing_enabled", "autoscaling_group_capacity_rebalance_enabled", "autoscaling_group_elb_health_check_enabled", @@ -2598,14 +2384,18 @@ "cloudfront_distributions_s3_origin_non_existent_bucket", "directconnect_connection_redundancy", "directconnect_virtual_interface_redundancy", - "dlm_ebs_snapshot_lifecycle_policy_exists", + "directoryservice_directory_snapshots_limit", "dms_instance_multi_az_enabled", "documentdb_cluster_deletion_protection", "documentdb_cluster_multi_az_enabled", "dynamodb_accelerator_cluster_multi_az", "dynamodb_table_autoscaling_enabled", "dynamodb_table_deletion_protection_enabled", + "ec2_elastic_ip_unassigned", "ec2_instance_detailed_monitoring_enabled", + "ec2_instance_older_than_specific_days", + "ec2_instance_paravirtual_type", + "ecr_repositories_lifecycle_policy_enabled", "ecs_cluster_container_insights_enabled", "ecs_task_definitions_containers_readonly_access", "ecs_task_definitions_logging_block_mode", @@ -2618,10 +2408,11 @@ "elbv2_cross_zone_load_balancing_enabled", "elbv2_deletion_protection", "elbv2_is_in_multiple_az", + "eventbridge_global_endpoint_event_replication_enabled", "fsx_windows_file_system_multi_az_enabled", - "iam_no_expired_server_certificates_stored", "kafka_cluster_enhanced_monitoring_enabled", "kms_cmk_not_deleted_unintentionally", + "lightsail_static_ip_unused", "mq_broker_active_deployment_mode", "mq_broker_cluster_deployment_mode", "neptune_cluster_deletion_protection", @@ -2632,21 +2423,13 @@ "opensearch_service_domains_fault_tolerant_master_nodes", "rds_cluster_deletion_protection", "rds_cluster_multi_az", - "rds_instance_certificate_expiration", "rds_instance_deletion_protection", - "rds_instance_deprecated_engine_version", + "rds_instance_enhanced_monitoring_enabled", "rds_instance_multi_az", "redshift_cluster_multi_az_enabled", + "resourceexplorer2_indexes_found", "s3_bucket_cross_region_replication", - "s3_bucket_no_mfa_delete", - "s3_bucket_object_lock", - "s3_bucket_object_versioning", "sagemaker_endpoint_config_prod_variant_instances", - "shield_advanced_protection_in_classic_load_balancers", - "shield_advanced_protection_in_global_accelerators", - "shield_advanced_protection_in_internet_facing_load_balancers", - "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", "vpc_different_regions", "vpc_endpoint_multi_az_enabled", "vpc_subnet_different_az", @@ -2688,9 +2471,9 @@ "backup_plans_exist", "backup_recovery_point_encrypted", "backup_reportplans_exist", + "backup_vaults_encrypted", "backup_vaults_exist", "cloudfront_distributions_multiple_origin_failover_configured", - "directoryservice_directory_snapshots_limit", "dlm_ebs_snapshot_lifecycle_policy_exists", "documentdb_cluster_backup_enabled", "dynamodb_table_protected_by_backup_plan", @@ -2699,22 +2482,16 @@ "ec2_ebs_volume_snapshots_exists", "efs_have_backup_enabled", "elasticache_redis_cluster_backup_enabled", - "fsx_file_system_copy_tags_to_backups_enabled", "lightsail_instance_automated_snapshots", "neptune_cluster_backup_enabled", - "neptune_cluster_copy_tags_to_snapshots", - "neptune_cluster_public_snapshot", - "neptune_cluster_snapshot_encrypted", "rds_cluster_backtrack_enabled", - "rds_cluster_copy_tags_to_snapshots", "rds_cluster_protected_by_backup_plan", "rds_instance_backup_enabled", - "rds_instance_copy_tags_to_snapshots", "rds_instance_protected_by_backup_plan", - "rds_snapshots_encrypted", - "rds_snapshots_public_access", "redshift_cluster_automated_snapshot", - "s3_bucket_lifecycle_enabled" + "s3_bucket_lifecycle_enabled", + "s3_bucket_object_lock", + "s3_bucket_object_versioning" ], "Attributes": [ { @@ -2756,7 +2533,6 @@ "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", "bedrock_model_invocation_logging_enabled", "bedrock_model_invocation_logs_encryption_enabled", - "cloudformation_stack_outputs_find_secrets", "cloudfront_distributions_logging_enabled", "cloudtrail_bucket_requires_mfa_delete", "cloudtrail_cloudwatch_logging_enabled", @@ -2776,14 +2552,11 @@ "cloudwatch_changes_to_network_gateways_alarm_configured", "cloudwatch_changes_to_network_route_tables_alarm_configured", "cloudwatch_changes_to_vpcs_alarm_configured", - "cloudwatch_log_group_kms_encryption_enabled", "cloudwatch_log_group_no_critical_pii_in_logs", "cloudwatch_log_group_no_secrets_in_logs", - "cloudwatch_log_group_not_publicly_accessible", "cloudwatch_log_group_retention_policy_specific_days_enabled", "codebuild_project_logging_enabled", "codebuild_project_s3_logs_encrypted", - "config_recorder_all_regions_enabled", "datasync_task_logging_enabled", "directoryservice_directory_log_forwarding_enabled", "directoryservice_directory_monitor_notifications", @@ -2795,22 +2568,14 @@ "elasticbeanstalk_environment_cloudwatch_logging_enabled", "elb_logging_enabled", "elbv2_logging_enabled", - "eventbridge_global_endpoint_event_replication_enabled", - "glue_development_endpoints_cloudwatch_logs_encryption_enabled", - "glue_etl_jobs_cloudwatch_logs_encryption_enabled", "glue_etl_jobs_logging_enabled", - "kafka_cluster_enhanced_monitoring_enabled", + "guardduty_eks_audit_log_enabled", "mq_broker_logging_enabled", "neptune_cluster_integration_cloudwatch_logs", "networkfirewall_logging_enabled", "opensearch_service_domains_audit_logging_enabled", "opensearch_service_domains_cloudwatch_logging_enabled", - "rds_cluster_critical_event_subscription", "rds_cluster_integration_cloudwatch_logs", - "rds_instance_critical_event_subscription", - "rds_instance_enhanced_monitoring_enabled", - "rds_instance_event_subscription_parameter_groups", - "rds_instance_event_subscription_security_groups", "rds_instance_integration_cloudwatch_logs", "redshift_cluster_audit_logging", "route53_public_hosted_zones_cloudwatch_logging_enabled", @@ -2898,7 +2663,7 @@ "Section": "2.9.6 Time Synchronization", "AuditChecklist": [ "Is the system time synchronized with the standard time?", - "Is regular inspection conducted to ensure that time synchronization is functioning properly?'" + "Is regular inspection conducted to ensure that time synchronization is functioning properly?" ], "RelatedRegulations": [], "AuditEvidence": [ @@ -2954,8 +2719,6 @@ "Description": "For each type of security system, an administrator must be designated, and operational procedures such as updating to the latest policies, modifying rule sets, and monitoring events must be established and implemented. The status of policy application for each security system must be managed.", "Checks": [ "apigateway_restapi_waf_acl_attached", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", "cloudfront_distributions_using_waf", "cloudtrail_bucket_requires_mfa_delete", "cloudtrail_cloudwatch_logging_enabled", @@ -3001,8 +2764,6 @@ "dms_instance_minor_version_upgrade_enabled", "dms_instance_multi_az_enabled", "dms_instance_no_public_access", - "ec2_client_vpn_endpoint_connection_logging_enabled", - "ec2_instance_managed_by_ssm", "elbv2_waf_acl_attached", "fms_policy_compliant", "guardduty_centrally_managed", @@ -3037,7 +2798,6 @@ "shield_advanced_protection_in_internet_facing_load_balancers", "shield_advanced_protection_in_route53_hosted_zones", "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", "waf_global_rule_with_conditions", "waf_global_rulegroup_not_empty", "waf_global_webacl_logging_enabled", @@ -3105,10 +2865,8 @@ "apigateway_restapi_logging_enabled", "apigateway_restapi_public", "apigateway_restapi_public_with_authorizer", - "apigateway_restapi_tracing_enabled", "apigateway_restapi_waf_acl_attached", "apigatewayv2_api_access_logging_enabled", - "apigatewayv2_api_authorizers_enabled", "appstream_fleet_default_internet_access_disabled", "appstream_fleet_maximum_session_duration", "appstream_fleet_session_disconnect_timeout", @@ -3116,13 +2874,8 @@ "athena_workgroup_encryption", "athena_workgroup_enforce_configuration", "athena_workgroup_logging_enabled", - "autoscaling_group_capacity_rebalance_enabled", - "autoscaling_group_elb_health_check_enabled", "autoscaling_group_launch_configuration_no_public_ip", "autoscaling_group_launch_configuration_requires_imdsv2", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "autoscaling_group_using_ec2_launch_template", "awslambda_function_inside_vpc", "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", "awslambda_function_no_secrets_in_code", @@ -3131,19 +2884,14 @@ "awslambda_function_url_cors_policy", "awslambda_function_url_public", "awslambda_function_using_supported_runtimes", - "awslambda_function_vpc_multi_az", - "backup_plans_exist", "backup_recovery_point_encrypted", - "backup_reportplans_exist", "backup_vaults_encrypted", - "backup_vaults_exist", "bedrock_agent_guardrail_enabled", "bedrock_guardrail_prompt_attack_filter_enabled", "bedrock_guardrail_sensitive_information_filter_enabled", "bedrock_model_invocation_logging_enabled", "bedrock_model_invocation_logs_encryption_enabled", "cloudformation_stack_outputs_find_secrets", - "cloudformation_stacks_termination_protection_enabled", "cloudfront_distributions_custom_ssl_certificate", "cloudfront_distributions_default_root_object", "cloudfront_distributions_field_level_encryption_enabled", @@ -3151,10 +2899,8 @@ "cloudfront_distributions_https_enabled", "cloudfront_distributions_https_sni_enabled", "cloudfront_distributions_logging_enabled", - "cloudfront_distributions_multiple_origin_failover_configured", "cloudfront_distributions_origin_traffic_encrypted", "cloudfront_distributions_s3_origin_access_control", - "cloudfront_distributions_s3_origin_non_existent_bucket", "cloudfront_distributions_using_deprecated_ssl_protocols", "cloudfront_distributions_using_waf", "cloudtrail_bucket_requires_mfa_delete", @@ -3163,7 +2909,6 @@ "cloudtrail_kms_encryption_enabled", "cloudtrail_log_file_validation_enabled", "cloudtrail_logs_s3_bucket_access_logging_enabled", - "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", "cloudtrail_multi_region_enabled", "cloudtrail_multi_region_enabled_logging_management_events", "cloudtrail_s3_dataevents_read_enabled", @@ -3197,10 +2942,8 @@ "codeartifact_packages_external_public_publishing_disabled", "codebuild_project_logging_enabled", "codebuild_project_no_secrets_in_variables", - "codebuild_project_older_90_days", "codebuild_project_s3_logs_encrypted", "codebuild_project_source_repo_url_no_sensitive_credentials", - "codebuild_project_user_controlled_buildspec", "codebuild_report_group_export_encrypted", "cognito_identity_pool_guest_access_disabled", "cognito_user_pool_advanced_security_enabled", @@ -3221,37 +2964,24 @@ "config_recorder_all_regions_enabled", "config_recorder_using_aws_service_role", "datasync_task_logging_enabled", - "directconnect_connection_redundancy", - "directconnect_virtual_interface_redundancy", "directoryservice_directory_log_forwarding_enabled", "directoryservice_directory_monitor_notifications", - "directoryservice_directory_snapshots_limit", "directoryservice_ldap_certificate_expiration", "directoryservice_radius_server_security_protocol", "directoryservice_supported_mfa_radius_enabled", - "dlm_ebs_snapshot_lifecycle_policy_exists", "dms_endpoint_mongodb_authentication_enabled", "dms_endpoint_neptune_iam_authorization_enabled", "dms_endpoint_ssl_enabled", "dms_instance_minor_version_upgrade_enabled", - "dms_instance_multi_az_enabled", "dms_instance_no_public_access", - "documentdb_cluster_backup_enabled", "documentdb_cluster_cloudwatch_log_export", - "documentdb_cluster_deletion_protection", - "documentdb_cluster_multi_az_enabled", "documentdb_cluster_public_snapshot", "documentdb_cluster_storage_encrypted", "drs_job_exist", "dynamodb_accelerator_cluster_encryption_enabled", "dynamodb_accelerator_cluster_in_transit_encryption_enabled", - "dynamodb_accelerator_cluster_multi_az", - "dynamodb_table_autoscaling_enabled", "dynamodb_table_cross_account_access", - "dynamodb_table_deletion_protection_enabled", - "dynamodb_table_protected_by_backup_plan", "dynamodb_tables_kms_cmk_encryption_enabled", - "dynamodb_tables_pitr_enabled", "ec2_ami_public", "ec2_client_vpn_endpoint_connection_logging_enabled", "ec2_ebs_default_encryption", @@ -3259,17 +2989,11 @@ "ec2_ebs_snapshot_account_block_public_access", "ec2_ebs_snapshots_encrypted", "ec2_ebs_volume_encryption", - "ec2_ebs_volume_protected_by_backup_plan", - "ec2_ebs_volume_snapshots_exists", "ec2_elastic_ip_shodan", - "ec2_elastic_ip_unassigned", "ec2_instance_account_imdsv2_enabled", - "ec2_instance_detailed_monitoring_enabled", "ec2_instance_imdsv2_enabled", "ec2_instance_internet_facing_with_instance_profile", "ec2_instance_managed_by_ssm", - "ec2_instance_older_than_specific_days", - "ec2_instance_paravirtual_type", "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_cifs_exposed_to_internet", "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", @@ -3321,17 +3045,12 @@ "ec2_securitygroup_with_many_ingress_egress_rules", "ec2_transitgateway_auto_accept_vpc_attachments", "ecr_registry_scan_images_on_push_enabled", - "ecr_repositories_lifecycle_policy_enabled", "ecr_repositories_not_publicly_accessible", "ecr_repositories_scan_vulnerabilities_in_latest_image", - "ecr_repositories_tag_immutability", - "ecs_cluster_container_insights_enabled", "ecs_service_fargate_latest_platform_version", "ecs_service_no_assign_public_ip", - "ecs_task_definitions_containers_readonly_access", "ecs_task_definitions_host_namespace_not_shared", "ecs_task_definitions_host_networking_mode_users", - "ecs_task_definitions_logging_block_mode", "ecs_task_definitions_logging_enabled", "ecs_task_definitions_no_environment_secrets", "ecs_task_definitions_no_privileged_containers", @@ -3339,7 +3058,6 @@ "efs_access_point_enforce_root_directory", "efs_access_point_enforce_user_identity", "efs_encryption_at_rest_enabled", - "efs_have_backup_enabled", "efs_mount_target_not_publicly_accessible", "efs_not_publicly_accessible", "eks_cluster_kms_cmk_encryption_in_secrets_enabled", @@ -3350,30 +3068,20 @@ "eks_control_plane_logging_all_types_enabled", "elasticache_cluster_uses_public_subnet", "elasticache_redis_cluster_auto_minor_version_upgrades", - "elasticache_redis_cluster_automatic_failover_enabled", - "elasticache_redis_cluster_backup_enabled", "elasticache_redis_cluster_in_transit_encryption_enabled", - "elasticache_redis_cluster_multi_az_enabled", "elasticache_redis_cluster_rest_encryption_enabled", "elasticache_redis_replication_group_auth_enabled", "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "elasticbeanstalk_environment_enhanced_health_reporting", "elasticbeanstalk_environment_managed_updates_enabled", - "elb_connection_draining_enabled", - "elb_cross_zone_load_balancing_enabled", "elb_desync_mitigation_mode", "elb_insecure_ssl_ciphers", "elb_internet_facing", - "elb_is_in_multiple_az", "elb_logging_enabled", "elb_ssl_listeners", "elb_ssl_listeners_use_acm_certificate", - "elbv2_cross_zone_load_balancing_enabled", - "elbv2_deletion_protection", "elbv2_desync_mitigation_mode", "elbv2_insecure_ssl_ciphers", "elbv2_internet_facing", - "elbv2_is_in_multiple_az", "elbv2_listeners_underneath", "elbv2_logging_enabled", "elbv2_nlb_tls_termination_enabled", @@ -3384,12 +3092,8 @@ "emr_cluster_publicly_accesible", "eventbridge_bus_cross_account_access", "eventbridge_bus_exposed", - "eventbridge_global_endpoint_event_replication_enabled", "eventbridge_schema_registry_cross_account_access", "fms_policy_compliant", - "fsx_file_system_copy_tags_to_backups_enabled", - "fsx_file_system_copy_tags_to_volumes_enabled", - "fsx_windows_file_system_multi_az_enabled", "glacier_vaults_policy_public_access", "glue_data_catalogs_connection_passwords_encryption_enabled", "glue_data_catalogs_metadata_encryption_enabled", @@ -3457,7 +3161,6 @@ "inspector2_active_findings_exist", "inspector2_is_enabled", "kafka_cluster_encryption_at_rest_uses_cmk", - "kafka_cluster_enhanced_monitoring_enabled", "kafka_cluster_in_transit_encryption_enabled", "kafka_cluster_is_public", "kafka_cluster_mutual_tls_authentication_enabled", @@ -3466,25 +3169,16 @@ "kafka_connector_in_transit_encryption_enabled", "kinesis_stream_encrypted_at_rest", "kms_cmk_are_used", - "kms_cmk_not_deleted_unintentionally", "kms_cmk_rotation_enabled", "kms_key_not_publicly_accessible", "lightsail_database_public", - "lightsail_instance_automated_snapshots", "lightsail_instance_public", - "lightsail_static_ip_unused", "macie_automated_sensitive_data_discovery_enabled", "macie_is_enabled", - "mq_broker_active_deployment_mode", "mq_broker_auto_minor_version_upgrades", - "mq_broker_cluster_deployment_mode", "mq_broker_logging_enabled", - "neptune_cluster_backup_enabled", - "neptune_cluster_copy_tags_to_snapshots", - "neptune_cluster_deletion_protection", "neptune_cluster_iam_authentication_enabled", "neptune_cluster_integration_cloudwatch_logs", - "neptune_cluster_multi_az", "neptune_cluster_public_snapshot", "neptune_cluster_snapshot_encrypted", "neptune_cluster_storage_encrypted", @@ -3492,15 +3186,12 @@ "networkfirewall_deletion_protection", "networkfirewall_in_all_vpc", "networkfirewall_logging_enabled", - "networkfirewall_multi_az", "networkfirewall_policy_default_action_fragmented_packets", "networkfirewall_policy_default_action_full_packets", "networkfirewall_policy_rule_group_associated", "opensearch_service_domains_audit_logging_enabled", "opensearch_service_domains_cloudwatch_logging_enabled", "opensearch_service_domains_encryption_at_rest_enabled", - "opensearch_service_domains_fault_tolerant_data_nodes", - "opensearch_service_domains_fault_tolerant_master_nodes", "opensearch_service_domains_https_communications_enforced", "opensearch_service_domains_internal_user_database_enabled", "opensearch_service_domains_node_to_node_encryption_enabled", @@ -3511,52 +3202,33 @@ "organizations_delegated_administrators", "organizations_opt_out_ai_services_policy", "organizations_scp_check_deny_regions", - "organizations_tags_policies_enabled_and_attached", - "rds_cluster_backtrack_enabled", - "rds_cluster_copy_tags_to_snapshots", "rds_cluster_critical_event_subscription", - "rds_cluster_default_admin", - "rds_cluster_deletion_protection", "rds_cluster_iam_authentication_enabled", "rds_cluster_integration_cloudwatch_logs", "rds_cluster_minor_version_upgrade_enabled", - "rds_cluster_multi_az", "rds_cluster_non_default_port", - "rds_cluster_protected_by_backup_plan", "rds_cluster_storage_encrypted", - "rds_instance_backup_enabled", "rds_instance_certificate_expiration", - "rds_instance_copy_tags_to_snapshots", "rds_instance_critical_event_subscription", - "rds_instance_default_admin", - "rds_instance_deletion_protection", "rds_instance_deprecated_engine_version", - "rds_instance_enhanced_monitoring_enabled", "rds_instance_event_subscription_parameter_groups", "rds_instance_event_subscription_security_groups", "rds_instance_iam_authentication_enabled", "rds_instance_inside_vpc", "rds_instance_integration_cloudwatch_logs", "rds_instance_minor_version_upgrade_enabled", - "rds_instance_multi_az", "rds_instance_no_public_access", "rds_instance_non_default_port", - "rds_instance_protected_by_backup_plan", "rds_instance_storage_encrypted", "rds_instance_transport_encrypted", "rds_snapshots_encrypted", "rds_snapshots_public_access", "redshift_cluster_audit_logging", - "redshift_cluster_automated_snapshot", "redshift_cluster_automatic_upgrades", "redshift_cluster_encrypted_at_rest", "redshift_cluster_enhanced_vpc_routing", "redshift_cluster_in_transit_encryption_enabled", - "redshift_cluster_multi_az_enabled", - "redshift_cluster_non_default_database_name", - "redshift_cluster_non_default_username", "redshift_cluster_public_access", - "resourceexplorer2_indexes_found", "route53_dangling_ip_subdomain_takeover", "route53_domains_privacy_protection_enabled", "route53_domains_transferlock_enabled", @@ -3565,15 +3237,11 @@ "s3_account_level_public_access_blocks", "s3_bucket_acl_prohibited", "s3_bucket_cross_account_access", - "s3_bucket_cross_region_replication", "s3_bucket_default_encryption", "s3_bucket_event_notifications_enabled", "s3_bucket_kms_encryption", "s3_bucket_level_public_access_block", - "s3_bucket_lifecycle_enabled", "s3_bucket_no_mfa_delete", - "s3_bucket_object_lock", - "s3_bucket_object_versioning", "s3_bucket_policy_public_write_access", "s3_bucket_public_access", "s3_bucket_public_list_acl", @@ -3581,7 +3249,6 @@ "s3_bucket_secure_transport_policy", "s3_bucket_server_access_logging_enabled", "s3_multi_region_access_point_public_access_block", - "sagemaker_endpoint_config_prod_variant_instances", "sagemaker_models_network_isolation_enabled", "sagemaker_models_vpc_settings_configured", "sagemaker_notebook_instance_encryption_enabled", @@ -3616,18 +3283,13 @@ "storagegateway_fileshare_encryption_enabled", "transfer_server_in_transit_encryption_enabled", "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", - "vpc_different_regions", "vpc_endpoint_connections_trust_boundaries", "vpc_endpoint_for_ec2_enabled", - "vpc_endpoint_multi_az_enabled", "vpc_endpoint_services_allowed_principals_trust_boundaries", "vpc_flow_logs_enabled", "vpc_peering_routing_tables_with_least_privilege", - "vpc_subnet_different_az", "vpc_subnet_no_public_ip_by_default", "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", "waf_global_rule_with_conditions", "waf_global_rulegroup_not_empty", "waf_global_webacl_logging_enabled", @@ -3676,41 +3338,7 @@ "Id": "2.10.3", "Name": "Public Server Security", "Description": "For servers exposed to external networks, protective measures must be established and implemented, including separating them from internal networks, conducting vulnerability assessments, access control, authentication, and establishing procedures for information collection, storage, and disclosure.", - "Checks": [ - "acm_certificates_expiration_check", - "acm_certificates_transparency_logs_enabled", - "acm_certificates_with_secure_key_algorithms", - "apigateway_restapi_client_certificate_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", - "apigateway_restapi_waf_acl_attached", - "cloudfront_distributions_s3_origin_non_existent_bucket", - "cloudfront_distributions_using_waf", - "cognito_user_pool_waf_acl_attached", - "elb_desync_mitigation_mode", - "elb_insecure_ssl_ciphers", - "elb_internet_facing", - "elb_ssl_listeners", - "elb_ssl_listeners_use_acm_certificate", - "elbv2_desync_mitigation_mode", - "elbv2_insecure_ssl_ciphers", - "elbv2_internet_facing", - "elbv2_listeners_underneath", - "elbv2_nlb_tls_termination_enabled", - "elbv2_ssl_listeners", - "elbv2_waf_acl_attached", - "lightsail_database_public", - "lightsail_instance_public", - "lightsail_static_ip_unused", - "route53_dangling_ip_subdomain_takeover", - "route53_domains_privacy_protection_enabled", - "shield_advanced_protection_in_associated_elastic_ips", - "shield_advanced_protection_in_classic_load_balancers", - "shield_advanced_protection_in_cloudfront_distributions", - "shield_advanced_protection_in_global_accelerators", - "shield_advanced_protection_in_internet_facing_load_balancers", - "shield_advanced_protection_in_route53_hosted_zones" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -3952,12 +3580,6 @@ "Name": "Establishment of Incident Prevention and Response System", "Description": "To prevent incidents such as security breaches and personal information leaks, and to respond quickly and effectively in the event of an incident, the organization must establish procedures for detecting, responding to, analyzing, and sharing internal and external intrusion attempts. In addition, the organization must establish a cooperative system with relevant external institutions and experts.", "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", - "account_security_questions_are_registered_in_the_aws_account", - "acm_certificates_with_secure_key_algorithms", - "guardduty_centrally_managed", "iam_support_role_created", "ssmincidents_enabled_with_plans" ], @@ -3996,557 +3618,9 @@ "Name": "Vulnerability Inspection and Remediation", "Description": "Regular vulnerability inspections must be conducted to verify whether information systems have exposed vulnerabilities, and any identified vulnerabilities must be promptly addressed. In addition, the organization must continuously monitor for new security vulnerabilities, assess their impact on the information systems, and take necessary actions.", "Checks": [ - "accessanalyzer_enabled", - "accessanalyzer_enabled_without_findings", - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", - "account_security_questions_are_registered_in_the_aws_account", - "acm_certificates_expiration_check", - "acm_certificates_transparency_logs_enabled", - "acm_certificates_with_secure_key_algorithms", - "apigateway_restapi_authorizers_enabled", - "apigateway_restapi_cache_encrypted", - "apigateway_restapi_client_certificate_enabled", - "apigateway_restapi_logging_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", - "apigateway_restapi_tracing_enabled", - "apigateway_restapi_waf_acl_attached", - "apigatewayv2_api_access_logging_enabled", - "apigatewayv2_api_authorizers_enabled", - "appstream_fleet_default_internet_access_disabled", - "appstream_fleet_maximum_session_duration", - "appstream_fleet_session_disconnect_timeout", - "appstream_fleet_session_idle_disconnect_timeout", - "athena_workgroup_encryption", - "athena_workgroup_enforce_configuration", - "athena_workgroup_logging_enabled", - "autoscaling_group_capacity_rebalance_enabled", - "autoscaling_group_elb_health_check_enabled", - "autoscaling_group_launch_configuration_no_public_ip", - "autoscaling_group_launch_configuration_requires_imdsv2", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "autoscaling_group_using_ec2_launch_template", - "awslambda_function_inside_vpc", - "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", - "awslambda_function_no_secrets_in_code", - "awslambda_function_no_secrets_in_variables", - "awslambda_function_not_publicly_accessible", - "awslambda_function_url_cors_policy", - "awslambda_function_url_public", - "awslambda_function_using_supported_runtimes", - "awslambda_function_vpc_multi_az", - "backup_plans_exist", - "backup_recovery_point_encrypted", - "backup_reportplans_exist", - "backup_vaults_encrypted", - "backup_vaults_exist", - "bedrock_agent_guardrail_enabled", - "bedrock_guardrail_prompt_attack_filter_enabled", - "bedrock_guardrail_sensitive_information_filter_enabled", - "bedrock_model_invocation_logging_enabled", - "bedrock_model_invocation_logs_encryption_enabled", - "cloudformation_stack_outputs_find_secrets", - "cloudformation_stacks_termination_protection_enabled", - "cloudfront_distributions_custom_ssl_certificate", - "cloudfront_distributions_default_root_object", - "cloudfront_distributions_field_level_encryption_enabled", - "cloudfront_distributions_geo_restrictions_enabled", - "cloudfront_distributions_https_enabled", - "cloudfront_distributions_https_sni_enabled", - "cloudfront_distributions_logging_enabled", - "cloudfront_distributions_multiple_origin_failover_configured", - "cloudfront_distributions_origin_traffic_encrypted", - "cloudfront_distributions_s3_origin_access_control", - "cloudfront_distributions_s3_origin_non_existent_bucket", - "cloudfront_distributions_using_deprecated_ssl_protocols", - "cloudfront_distributions_using_waf", - "cloudtrail_bucket_requires_mfa_delete", - "cloudtrail_cloudwatch_logging_enabled", - "cloudtrail_insights_exist", - "cloudtrail_kms_encryption_enabled", - "cloudtrail_log_file_validation_enabled", - "cloudtrail_logs_s3_bucket_access_logging_enabled", - "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", - "cloudtrail_multi_region_enabled", - "cloudtrail_multi_region_enabled_logging_management_events", - "cloudtrail_s3_dataevents_read_enabled", - "cloudtrail_s3_dataevents_write_enabled", - "cloudtrail_threat_detection_enumeration", - "cloudtrail_threat_detection_llm_jacking", - "cloudtrail_threat_detection_privilege_escalation", - "cloudwatch_alarm_actions_alarm_state_configured", - "cloudwatch_alarm_actions_enabled", - "cloudwatch_changes_to_network_acls_alarm_configured", - "cloudwatch_changes_to_network_gateways_alarm_configured", - "cloudwatch_changes_to_network_route_tables_alarm_configured", - "cloudwatch_changes_to_vpcs_alarm_configured", - "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_group_kms_encryption_enabled", - "cloudwatch_log_group_no_critical_pii_in_logs", - "cloudwatch_log_group_no_secrets_in_logs", - "cloudwatch_log_group_not_publicly_accessible", - "cloudwatch_log_group_retention_policy_specific_days_enabled", - "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", - "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", - "cloudwatch_log_metric_filter_authentication_failures", - "cloudwatch_log_metric_filter_aws_organizations_changes", - "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", - "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", - "cloudwatch_log_metric_filter_policy_changes", - "cloudwatch_log_metric_filter_root_usage", - "cloudwatch_log_metric_filter_security_group_changes", - "cloudwatch_log_metric_filter_sign_in_without_mfa", - "cloudwatch_log_metric_filter_unauthorized_api_calls", - "codeartifact_packages_external_public_publishing_disabled", - "codebuild_project_logging_enabled", - "codebuild_project_no_secrets_in_variables", - "codebuild_project_older_90_days", - "codebuild_project_s3_logs_encrypted", - "codebuild_project_source_repo_url_no_sensitive_credentials", - "codebuild_project_user_controlled_buildspec", - "codebuild_report_group_export_encrypted", - "cognito_identity_pool_guest_access_disabled", - "cognito_user_pool_advanced_security_enabled", - "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", - "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", - "cognito_user_pool_client_prevent_user_existence_errors", - "cognito_user_pool_client_token_revocation_enabled", - "cognito_user_pool_deletion_protection_enabled", - "cognito_user_pool_mfa_enabled", - "cognito_user_pool_password_policy_lowercase", - "cognito_user_pool_password_policy_minimum_length_14", - "cognito_user_pool_password_policy_number", - "cognito_user_pool_password_policy_symbol", - "cognito_user_pool_password_policy_uppercase", - "cognito_user_pool_self_registration_disabled", - "cognito_user_pool_temporary_password_expiration", - "cognito_user_pool_waf_acl_attached", - "config_recorder_all_regions_enabled", - "config_recorder_using_aws_service_role", - "datasync_task_logging_enabled", - "directconnect_connection_redundancy", - "directconnect_virtual_interface_redundancy", - "directoryservice_directory_log_forwarding_enabled", - "directoryservice_directory_monitor_notifications", - "directoryservice_directory_snapshots_limit", - "directoryservice_ldap_certificate_expiration", - "directoryservice_radius_server_security_protocol", - "directoryservice_supported_mfa_radius_enabled", - "dlm_ebs_snapshot_lifecycle_policy_exists", - "dms_endpoint_mongodb_authentication_enabled", - "dms_endpoint_neptune_iam_authorization_enabled", - "dms_endpoint_ssl_enabled", - "dms_instance_minor_version_upgrade_enabled", - "dms_instance_multi_az_enabled", - "dms_instance_no_public_access", - "documentdb_cluster_backup_enabled", - "documentdb_cluster_cloudwatch_log_export", - "documentdb_cluster_deletion_protection", - "documentdb_cluster_multi_az_enabled", - "documentdb_cluster_public_snapshot", - "documentdb_cluster_storage_encrypted", - "drs_job_exist", - "dynamodb_accelerator_cluster_encryption_enabled", - "dynamodb_accelerator_cluster_in_transit_encryption_enabled", - "dynamodb_accelerator_cluster_multi_az", - "dynamodb_table_autoscaling_enabled", - "dynamodb_table_cross_account_access", - "dynamodb_table_deletion_protection_enabled", - "dynamodb_table_protected_by_backup_plan", - "dynamodb_tables_kms_cmk_encryption_enabled", - "dynamodb_tables_pitr_enabled", - "ec2_ami_public", - "ec2_client_vpn_endpoint_connection_logging_enabled", - "ec2_ebs_default_encryption", - "ec2_ebs_public_snapshot", - "ec2_ebs_snapshot_account_block_public_access", - "ec2_ebs_snapshots_encrypted", - "ec2_ebs_volume_encryption", - "ec2_ebs_volume_protected_by_backup_plan", - "ec2_ebs_volume_snapshots_exists", - "ec2_elastic_ip_shodan", - "ec2_elastic_ip_unassigned", - "ec2_instance_account_imdsv2_enabled", - "ec2_instance_detailed_monitoring_enabled", - "ec2_instance_imdsv2_enabled", - "ec2_instance_internet_facing_with_instance_profile", - "ec2_instance_managed_by_ssm", - "ec2_instance_older_than_specific_days", - "ec2_instance_paravirtual_type", - "ec2_instance_port_cassandra_exposed_to_internet", - "ec2_instance_port_cifs_exposed_to_internet", - "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", - "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", - "ec2_instance_port_ssh_exposed_to_internet", - "ec2_instance_port_telnet_exposed_to_internet", - "ec2_instance_profile_attached", - "ec2_instance_public_ip", - "ec2_instance_secrets_user_data", - "ec2_instance_uses_single_eni", - "ec2_launch_template_no_public_ip", - "ec2_launch_template_no_secrets", - "ec2_networkacl_allow_ingress_any_port", - "ec2_networkacl_allow_ingress_tcp_port_22", - "ec2_networkacl_allow_ingress_tcp_port_3389", - "ec2_networkacl_unused", - "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_any_port", - "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", - "ec2_securitygroup_allow_wide_open_public_ipv4", - "ec2_securitygroup_default_restrict_traffic", - "ec2_securitygroup_from_launch_wizard", - "ec2_securitygroup_not_used", - "ec2_securitygroup_with_many_ingress_egress_rules", - "ec2_transitgateway_auto_accept_vpc_attachments", "ecr_registry_scan_images_on_push_enabled", - "ecr_repositories_lifecycle_policy_enabled", - "ecr_repositories_not_publicly_accessible", "ecr_repositories_scan_vulnerabilities_in_latest_image", - "ecr_repositories_tag_immutability", - "ecs_cluster_container_insights_enabled", - "ecs_service_fargate_latest_platform_version", - "ecs_service_no_assign_public_ip", - "ecs_task_definitions_containers_readonly_access", - "ecs_task_definitions_host_namespace_not_shared", - "ecs_task_definitions_host_networking_mode_users", - "ecs_task_definitions_logging_block_mode", - "ecs_task_definitions_logging_enabled", - "ecs_task_definitions_no_environment_secrets", - "ecs_task_definitions_no_privileged_containers", - "ecs_task_set_no_assign_public_ip", - "efs_access_point_enforce_root_directory", - "efs_access_point_enforce_user_identity", - "efs_encryption_at_rest_enabled", - "efs_have_backup_enabled", - "efs_mount_target_not_publicly_accessible", - "efs_not_publicly_accessible", - "eks_cluster_kms_cmk_encryption_in_secrets_enabled", - "eks_cluster_network_policy_enabled", - "eks_cluster_not_publicly_accessible", - "eks_cluster_private_nodes_enabled", - "eks_cluster_uses_a_supported_version", - "eks_control_plane_logging_all_types_enabled", - "elasticache_cluster_uses_public_subnet", - "elasticache_redis_cluster_auto_minor_version_upgrades", - "elasticache_redis_cluster_automatic_failover_enabled", - "elasticache_redis_cluster_backup_enabled", - "elasticache_redis_cluster_in_transit_encryption_enabled", - "elasticache_redis_cluster_multi_az_enabled", - "elasticache_redis_cluster_rest_encryption_enabled", - "elasticache_redis_replication_group_auth_enabled", - "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "elasticbeanstalk_environment_enhanced_health_reporting", - "elasticbeanstalk_environment_managed_updates_enabled", - "elb_connection_draining_enabled", - "elb_cross_zone_load_balancing_enabled", - "elb_desync_mitigation_mode", - "elb_insecure_ssl_ciphers", - "elb_internet_facing", - "elb_is_in_multiple_az", - "elb_logging_enabled", - "elb_ssl_listeners", - "elb_ssl_listeners_use_acm_certificate", - "elbv2_cross_zone_load_balancing_enabled", - "elbv2_deletion_protection", - "elbv2_desync_mitigation_mode", - "elbv2_insecure_ssl_ciphers", - "elbv2_internet_facing", - "elbv2_is_in_multiple_az", - "elbv2_listeners_underneath", - "elbv2_logging_enabled", - "elbv2_nlb_tls_termination_enabled", - "elbv2_ssl_listeners", - "elbv2_waf_acl_attached", - "emr_cluster_account_public_block_enabled", - "emr_cluster_master_nodes_no_public_ip", - "emr_cluster_publicly_accesible", - "eventbridge_bus_cross_account_access", - "eventbridge_bus_exposed", - "eventbridge_global_endpoint_event_replication_enabled", - "eventbridge_schema_registry_cross_account_access", - "fms_policy_compliant", - "fsx_file_system_copy_tags_to_backups_enabled", - "fsx_file_system_copy_tags_to_volumes_enabled", - "fsx_windows_file_system_multi_az_enabled", - "glacier_vaults_policy_public_access", - "glue_data_catalogs_connection_passwords_encryption_enabled", - "glue_data_catalogs_metadata_encryption_enabled", - "glue_data_catalogs_not_publicly_accessible", - "glue_database_connections_ssl_enabled", - "glue_development_endpoints_cloudwatch_logs_encryption_enabled", - "glue_development_endpoints_job_bookmark_encryption_enabled", - "glue_development_endpoints_s3_encryption_enabled", - "glue_etl_jobs_amazon_s3_encryption_enabled", - "glue_etl_jobs_cloudwatch_logs_encryption_enabled", - "glue_etl_jobs_job_bookmark_encryption_enabled", - "glue_etl_jobs_logging_enabled", - "glue_ml_transform_encrypted_at_rest", - "guardduty_centrally_managed", - "guardduty_ec2_malware_protection_enabled", - "guardduty_eks_audit_log_enabled", - "guardduty_eks_runtime_monitoring_enabled", - "guardduty_is_enabled", - "guardduty_lambda_protection_enabled", - "guardduty_no_high_severity_findings", - "guardduty_rds_protection_enabled", - "guardduty_s3_protection_enabled", - "iam_administrator_access_with_mfa", - "iam_avoid_root_usage", - "iam_aws_attached_policy_no_administrative_privileges", - "iam_check_saml_providers_sts", - "iam_customer_attached_policy_no_administrative_privileges", - "iam_customer_unattached_policy_no_administrative_privileges", - "iam_group_administrator_access_policy", - "iam_inline_policy_allows_privilege_escalation", - "iam_inline_policy_no_administrative_privileges", - "iam_inline_policy_no_full_access_to_cloudtrail", - "iam_inline_policy_no_full_access_to_kms", - "iam_no_custom_policy_permissive_role_assumption", - "iam_no_expired_server_certificates_stored", - "iam_no_root_access_key", - "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_password_policy_lowercase", - "iam_password_policy_minimum_length_14", - "iam_password_policy_number", - "iam_password_policy_reuse_24", - "iam_password_policy_symbol", - "iam_password_policy_uppercase", - "iam_policy_allows_privilege_escalation", - "iam_policy_attached_only_to_group_or_roles", - "iam_policy_cloudshell_admin_not_attached", - "iam_policy_no_full_access_to_cloudtrail", - "iam_policy_no_full_access_to_kms", - "iam_role_administratoraccess_policy", - "iam_role_cross_account_readonlyaccess_policy", - "iam_role_cross_service_confused_deputy_prevention", - "iam_root_hardware_mfa_enabled", - "iam_root_mfa_enabled", - "iam_rotate_access_key_90_days", - "iam_securityaudit_role_created", - "iam_support_role_created", - "iam_user_accesskey_unused", - "iam_user_administrator_access_policy", - "iam_user_console_access_unused", - "iam_user_hardware_mfa_enabled", - "iam_user_mfa_enabled_console_access", - "iam_user_no_setup_initial_access_key", - "iam_user_two_active_access_key", - "iam_user_with_temporary_credentials", - "inspector2_active_findings_exist", - "inspector2_is_enabled", - "kafka_cluster_encryption_at_rest_uses_cmk", - "kafka_cluster_enhanced_monitoring_enabled", - "kafka_cluster_in_transit_encryption_enabled", - "kafka_cluster_is_public", - "kafka_cluster_mutual_tls_authentication_enabled", - "kafka_cluster_unrestricted_access_disabled", - "kafka_cluster_uses_latest_version", - "kafka_connector_in_transit_encryption_enabled", - "kinesis_stream_encrypted_at_rest", - "kms_cmk_are_used", - "kms_cmk_not_deleted_unintentionally", - "kms_cmk_rotation_enabled", - "kms_key_not_publicly_accessible", - "lightsail_database_public", - "lightsail_instance_automated_snapshots", - "lightsail_instance_public", - "lightsail_static_ip_unused", - "macie_automated_sensitive_data_discovery_enabled", - "macie_is_enabled", - "mq_broker_active_deployment_mode", - "mq_broker_auto_minor_version_upgrades", - "mq_broker_cluster_deployment_mode", - "mq_broker_logging_enabled", - "neptune_cluster_backup_enabled", - "neptune_cluster_copy_tags_to_snapshots", - "neptune_cluster_deletion_protection", - "neptune_cluster_iam_authentication_enabled", - "neptune_cluster_integration_cloudwatch_logs", - "neptune_cluster_multi_az", - "neptune_cluster_public_snapshot", - "neptune_cluster_snapshot_encrypted", - "neptune_cluster_storage_encrypted", - "neptune_cluster_uses_public_subnet", - "networkfirewall_deletion_protection", - "networkfirewall_in_all_vpc", - "networkfirewall_logging_enabled", - "networkfirewall_multi_az", - "networkfirewall_policy_default_action_fragmented_packets", - "networkfirewall_policy_default_action_full_packets", - "networkfirewall_policy_rule_group_associated", - "opensearch_service_domains_audit_logging_enabled", - "opensearch_service_domains_cloudwatch_logging_enabled", - "opensearch_service_domains_encryption_at_rest_enabled", - "opensearch_service_domains_fault_tolerant_data_nodes", - "opensearch_service_domains_fault_tolerant_master_nodes", - "opensearch_service_domains_https_communications_enforced", - "opensearch_service_domains_internal_user_database_enabled", - "opensearch_service_domains_node_to_node_encryption_enabled", - "opensearch_service_domains_not_publicly_accessible", - "opensearch_service_domains_updated_to_the_latest_service_software_version", - "opensearch_service_domains_use_cognito_authentication_for_kibana", - "organizations_account_part_of_organizations", - "organizations_delegated_administrators", - "organizations_opt_out_ai_services_policy", - "organizations_scp_check_deny_regions", - "organizations_tags_policies_enabled_and_attached", - "rds_cluster_backtrack_enabled", - "rds_cluster_copy_tags_to_snapshots", - "rds_cluster_critical_event_subscription", - "rds_cluster_default_admin", - "rds_cluster_deletion_protection", - "rds_cluster_iam_authentication_enabled", - "rds_cluster_integration_cloudwatch_logs", - "rds_cluster_minor_version_upgrade_enabled", - "rds_cluster_multi_az", - "rds_cluster_non_default_port", - "rds_cluster_protected_by_backup_plan", - "rds_cluster_storage_encrypted", - "rds_instance_backup_enabled", - "rds_instance_certificate_expiration", - "rds_instance_copy_tags_to_snapshots", - "rds_instance_critical_event_subscription", - "rds_instance_default_admin", - "rds_instance_deletion_protection", - "rds_instance_deprecated_engine_version", - "rds_instance_enhanced_monitoring_enabled", - "rds_instance_event_subscription_parameter_groups", - "rds_instance_event_subscription_security_groups", - "rds_instance_iam_authentication_enabled", - "rds_instance_inside_vpc", - "rds_instance_integration_cloudwatch_logs", - "rds_instance_minor_version_upgrade_enabled", - "rds_instance_multi_az", - "rds_instance_no_public_access", - "rds_instance_non_default_port", - "rds_instance_protected_by_backup_plan", - "rds_instance_storage_encrypted", - "rds_instance_transport_encrypted", - "rds_snapshots_encrypted", - "rds_snapshots_public_access", - "redshift_cluster_audit_logging", - "redshift_cluster_automated_snapshot", - "redshift_cluster_automatic_upgrades", - "redshift_cluster_encrypted_at_rest", - "redshift_cluster_enhanced_vpc_routing", - "redshift_cluster_in_transit_encryption_enabled", - "redshift_cluster_multi_az_enabled", - "redshift_cluster_non_default_database_name", - "redshift_cluster_non_default_username", - "redshift_cluster_public_access", - "resourceexplorer2_indexes_found", - "route53_dangling_ip_subdomain_takeover", - "route53_domains_privacy_protection_enabled", - "route53_domains_transferlock_enabled", - "route53_public_hosted_zones_cloudwatch_logging_enabled", - "s3_access_point_public_access_block", - "s3_account_level_public_access_blocks", - "s3_bucket_acl_prohibited", - "s3_bucket_cross_account_access", - "s3_bucket_cross_region_replication", - "s3_bucket_default_encryption", - "s3_bucket_event_notifications_enabled", - "s3_bucket_kms_encryption", - "s3_bucket_level_public_access_block", - "s3_bucket_lifecycle_enabled", - "s3_bucket_no_mfa_delete", - "s3_bucket_object_lock", - "s3_bucket_object_versioning", - "s3_bucket_policy_public_write_access", - "s3_bucket_public_access", - "s3_bucket_public_list_acl", - "s3_bucket_public_write_acl", - "s3_bucket_secure_transport_policy", - "s3_bucket_server_access_logging_enabled", - "s3_multi_region_access_point_public_access_block", - "sagemaker_endpoint_config_prod_variant_instances", - "sagemaker_models_network_isolation_enabled", - "sagemaker_models_vpc_settings_configured", - "sagemaker_notebook_instance_encryption_enabled", - "sagemaker_notebook_instance_root_access_disabled", - "sagemaker_notebook_instance_vpc_settings_configured", - "sagemaker_notebook_instance_without_direct_internet_access_configured", - "sagemaker_training_jobs_intercontainer_encryption_enabled", - "sagemaker_training_jobs_network_isolation_enabled", - "sagemaker_training_jobs_volume_and_output_encryption_enabled", - "sagemaker_training_jobs_vpc_settings_configured", - "secretsmanager_automatic_rotation_enabled", - "secretsmanager_not_publicly_accessible", - "secretsmanager_secret_rotated_periodically", - "secretsmanager_secret_unused", - "securityhub_enabled", - "ses_identity_not_publicly_accessible", - "shield_advanced_protection_in_associated_elastic_ips", - "shield_advanced_protection_in_classic_load_balancers", - "shield_advanced_protection_in_cloudfront_distributions", - "shield_advanced_protection_in_global_accelerators", - "shield_advanced_protection_in_internet_facing_load_balancers", - "shield_advanced_protection_in_route53_hosted_zones", - "sns_subscription_not_using_http_endpoints", - "sns_topics_kms_encryption_at_rest_enabled", - "sns_topics_not_publicly_accessible", - "sqs_queues_not_publicly_accessible", - "sqs_queues_server_side_encryption_enabled", - "ssm_document_secrets", - "ssm_documents_set_as_public", - "ssm_managed_compliant_patching", - "ssmincidents_enabled_with_plans", - "storagegateway_fileshare_encryption_enabled", - "transfer_server_in_transit_encryption_enabled", - "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", - "vpc_different_regions", - "vpc_endpoint_connections_trust_boundaries", - "vpc_endpoint_for_ec2_enabled", - "vpc_endpoint_multi_az_enabled", - "vpc_endpoint_services_allowed_principals_trust_boundaries", - "vpc_flow_logs_enabled", - "vpc_peering_routing_tables_with_least_privilege", - "vpc_subnet_different_az", - "vpc_subnet_no_public_ip_by_default", - "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", - "waf_global_rule_with_conditions", - "waf_global_rulegroup_not_empty", - "waf_global_webacl_logging_enabled", - "waf_global_webacl_with_rules", - "waf_regional_rule_with_conditions", - "waf_regional_rulegroup_not_empty", - "waf_regional_webacl_with_rules", - "wafv2_webacl_logging_enabled", - "wafv2_webacl_rule_logging_enabled", - "wafv2_webacl_with_rules", - "wellarchitected_workload_no_high_or_medium_risks", - "workspaces_volume_encryption_enabled", - "workspaces_vpc_2private_1public_subnets_nat" + "inspector2_is_enabled" ], "Attributes": [ { @@ -4583,16 +3657,11 @@ "Name": "Abnormal Behavior Analysis and Monitoring", "Description": "To quickly detect and respond to intrusion attempts, personal information leakage attempts, and fraudulent activities from internal or external sources, the organization must collect and analyze network and data flows. Post-monitoring and inspection actions must be timely.", "Checks": [ - "apigateway_restapi_logging_enabled", - "apigateway_restapi_public", - "apigateway_restapi_tracing_enabled", - "apigatewayv2_api_access_logging_enabled", - "athena_workgroup_logging_enabled", - "bedrock_model_invocation_logging_enabled", - "cloudfront_distributions_logging_enabled", + "cloudtrail_cloudwatch_logging_enabled", "cloudtrail_insights_exist", - "cloudtrail_log_file_validation_enabled", "cloudtrail_logs_s3_bucket_access_logging_enabled", + "cloudtrail_multi_region_enabled_logging_management_events", + "cloudtrail_s3_dataevents_read_enabled", "cloudtrail_s3_dataevents_write_enabled", "cloudtrail_threat_detection_enumeration", "cloudtrail_threat_detection_llm_jacking", @@ -4614,51 +3683,18 @@ "cloudwatch_log_metric_filter_security_group_changes", "cloudwatch_log_metric_filter_sign_in_without_mfa", "cloudwatch_log_metric_filter_unauthorized_api_calls", - "codebuild_project_logging_enabled", - "cognito_user_pool_advanced_security_enabled", "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", "config_recorder_all_regions_enabled", - "datasync_task_logging_enabled", - "directoryservice_directory_log_forwarding_enabled", - "directoryservice_directory_monitor_notifications", - "documentdb_cluster_cloudwatch_log_export", - "ec2_client_vpn_endpoint_connection_logging_enabled", - "ec2_elastic_ip_shodan", - "ec2_instance_detailed_monitoring_enabled", - "ecs_cluster_container_insights_enabled", - "ecs_task_definitions_logging_enabled", - "eks_control_plane_logging_all_types_enabled", - "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "elasticbeanstalk_environment_enhanced_health_reporting", - "elb_logging_enabled", - "elbv2_logging_enabled", - "glue_etl_jobs_logging_enabled", "guardduty_eks_audit_log_enabled", "guardduty_eks_runtime_monitoring_enabled", "guardduty_no_high_severity_findings", - "kafka_cluster_enhanced_monitoring_enabled", - "mq_broker_logging_enabled", - "neptune_cluster_integration_cloudwatch_logs", - "networkfirewall_logging_enabled", - "opensearch_service_domains_audit_logging_enabled", - "opensearch_service_domains_cloudwatch_logging_enabled", "rds_cluster_critical_event_subscription", - "rds_cluster_integration_cloudwatch_logs", "rds_instance_critical_event_subscription", - "rds_instance_enhanced_monitoring_enabled", "rds_instance_event_subscription_parameter_groups", "rds_instance_event_subscription_security_groups", - "rds_instance_integration_cloudwatch_logs", - "redshift_cluster_audit_logging", - "route53_public_hosted_zones_cloudwatch_logging_enabled", "s3_bucket_event_notifications_enabled", - "s3_bucket_server_access_logging_enabled", - "trustedadvisor_errors_and_warnings", - "vpc_flow_logs_enabled", - "waf_global_webacl_logging_enabled", - "wafv2_webacl_logging_enabled", - "wafv2_webacl_rule_logging_enabled" + "trustedadvisor_errors_and_warnings" ], "Attributes": [ { @@ -4717,11 +3753,7 @@ "Id": "2.11.5", "Name": "Incident Response and Recovery", "Description": "When signs of or actual incidents of security breaches or personal information leakage are detected, the organization must comply with legal notification and reporting obligations, respond and recover promptly according to established procedures, and analyze the incident to establish preventive measures to reflect in the response system.", - "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "2. Control Measures Requirements", @@ -4758,62 +3790,29 @@ "Name": "Safety Measures for Disaster Preparedness", "Description": "Identify types of disasters that could threaten the operational continuity of the organization's core services and systems, such as natural disasters, communication or power failures, and hacking. Analyze the expected scale of damage and impact for each type, define the recovery time objective (RTO) and recovery point objective (RPO), and establish a disaster recovery system including recovery strategies, emergency recovery teams, emergency contact networks, and recovery procedures.", "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", - "autoscaling_group_capacity_rebalance_enabled", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "awslambda_function_vpc_multi_az", "backup_plans_exist", + "backup_reportplans_exist", + "backup_vaults_exist", "cloudfront_distributions_multiple_origin_failover_configured", - "directconnect_connection_redundancy", - "directconnect_virtual_interface_redundancy", - "directoryservice_directory_snapshots_limit", - "dms_instance_multi_az_enabled", + "dlm_ebs_snapshot_lifecycle_policy_exists", "documentdb_cluster_backup_enabled", - "documentdb_cluster_multi_az_enabled", "drs_job_exist", - "dynamodb_accelerator_cluster_multi_az", - "dynamodb_table_autoscaling_enabled", "dynamodb_table_protected_by_backup_plan", "dynamodb_tables_pitr_enabled", "ec2_ebs_volume_protected_by_backup_plan", "ec2_ebs_volume_snapshots_exists", "efs_have_backup_enabled", - "elasticache_redis_cluster_automatic_failover_enabled", "elasticache_redis_cluster_backup_enabled", - "elasticache_redis_cluster_multi_az_enabled", - "elb_cross_zone_load_balancing_enabled", - "elb_is_in_multiple_az", - "elbv2_cross_zone_load_balancing_enabled", - "elbv2_is_in_multiple_az", - "eventbridge_global_endpoint_event_replication_enabled", - "fsx_file_system_copy_tags_to_backups_enabled", - "fsx_windows_file_system_multi_az_enabled", "lightsail_instance_automated_snapshots", - "mq_broker_active_deployment_mode", - "mq_broker_cluster_deployment_mode", "neptune_cluster_backup_enabled", - "neptune_cluster_multi_az", - "opensearch_service_domains_fault_tolerant_data_nodes", - "opensearch_service_domains_fault_tolerant_master_nodes", "rds_cluster_backtrack_enabled", - "rds_cluster_multi_az", "rds_cluster_protected_by_backup_plan", "rds_instance_backup_enabled", - "rds_instance_multi_az", "rds_instance_protected_by_backup_plan", "redshift_cluster_automated_snapshot", - "redshift_cluster_multi_az_enabled", - "s3_bucket_cross_region_replication", "s3_bucket_lifecycle_enabled", "s3_bucket_object_lock", - "s3_bucket_object_versioning", - "sagemaker_endpoint_config_prod_variant_instances", - "vpc_different_regions", - "vpc_endpoint_multi_az_enabled", - "vpc_subnet_different_az" + "s3_bucket_object_versioning" ], "Attributes": [ { @@ -5157,16 +4156,7 @@ "Personal information flowchart", "Registration status of personal information files", "Personal information file management ledger", - "Personal information processing policy-related personal information files", - "Personal information files related to investigations under the Punishment of Tax Offenses Act and the Customs Act", - "Personal information files for one-time operations deemed to have a low need for continuous management as determined by Presidential Decree", - "Personal information files for simple tasks such as attending meetings, sending documents or materials, and financial settlements, which have a low need for continuous management", - "Personal information files processed temporarily for public health or public safety emergencies", - "Other personal information files collected for one-time tasks that are not stored or recorded", - "Personal information files classified as confidential under other laws", - "Personal information files collected or requested for analysis related to national security", - "Personal video information files processed via video information processing devices", - "Personal information files retained by financial institutions for handling financial transactions under the Real Name Financial Transactions and Guarantee of Secrecy Act" + "Personal information processing policy" ], "NonComplianceCases": [ "Case 1: Although personal information files are managed through the website's personal information file registration menu, some personal information files related to website services are missing from the personal information processing policy.", @@ -5291,20 +4281,9 @@ "Is the processing period for pseudonymized information set to an appropriate period considering the processing purpose, and is the information destroyed without delay when that period expires?", "When anonymizing personal information, is the information anonymized to a level where individuals cannot be identified even with the use of additional information, considering the time, cost, and technology available?" ], - "RelatedRegulations": [ - "Personal Information Protection Act, Article 2 (Definitions), Article 28-2 (Processing of Pseudonymized Information), Article 28-3 (Restrictions on Combining Pseudonymized Information), Article 28-4 (Obligations for the Safe Processing of Pseudonymized Information), Article 28-5 (Prohibition of Re-identification in Processing Pseudonymized Information), Article 28-7 (Scope of Application), Article 58-2 (Exemptions)" - ], - "AuditEvidence": [ - "Procedures and results of the adequacy review of pseudonymization/anonymization", - "Records of pseudonymized information processing", - "Privacy policy (regarding the use and provision of pseudonymized information)" - ], - "NonComplianceCases": [ - "Case 1: When processing pseudonymized information for statistical purposes or scientific research without obtaining consent from data subjects, records of the pseudonymization process were not kept, or the privacy policy was not updated to include relevant information.", - "Case 2: Additional information was not stored separately from pseudonymized information in the same database, or access rights to both sets of information were not appropriately segregated.", - "Case 3: Although pseudonymized personal information was used, the pseudonymization process was not sufficient, making it possible to identify individuals by combining the information with other data without using additional information.", - "Case 4: Personal information was anonymized for generating test data or for public release, but due to outliers or other factors, it was still possible to identify individuals, indicating that the anonymization process was not sufficient." - ] + "RelatedRegulations": [], + "AuditEvidence": [], + "NonComplianceCases": [] } ] }, @@ -5394,7 +4373,7 @@ "When receiving personal information, does the recipient notify the data subjects without delay regarding the fact that personal information has been received and other necessary matters, if legally required?", "Does the recipient of the personal information use the information only for its original purpose at the time of transfer, or provide it to third parties in compliance with the original purpose?" ], - "RelatedRegulations": [ + "RelatedRegulations": [ "Personal Information Protection Act, Article 27 (Restrictions on the Transfer of Personal Information Due to Business Transfers)" ], "AuditEvidence": [ @@ -5496,7 +4475,7 @@ "Personal Information Protection Act, Article 21 (Destruction of Personal Information)" ], "AuditEvidence": [ - "Regulations regarding the retention period and destruction of personal information',", + "Regulations regarding the retention period and destruction of personal information", "Current status of separated databases (table structure, etc.)", "Access permissions for separated databases" ], @@ -5609,4 +4588,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/prowler/compliance/aws/kisa_isms_p_2023_korean_aws.json b/prowler/compliance/aws/kisa_isms_p_2023_korean_aws.json index acde21a745..33ca1364f4 100644 --- a/prowler/compliance/aws/kisa_isms_p_2023_korean_aws.json +++ b/prowler/compliance/aws/kisa_isms_p_2023_korean_aws.json @@ -12,7 +12,7 @@ "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", - "Subdomain": "1.1 관리체계", + "Subdomain": "1.1 관리체계 기반 마련", "Section": "1.1.1 경영진의 참여", "AuditChecklist": [ "정보보호 및 개인정보보호 관리체계의 수립 및 운영활동 전반에 경영진의 참여가 이루어질 수 있도록 보고 및 의사결정 등의 책임과 역할을 문서화하고 있는가?", @@ -41,7 +41,7 @@ "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", - "Subdomain": "1.1 관리체계", + "Subdomain": "1.1 관리체계 기반 마련", "Section": "1.1.2 최고책임자의 지정", "AuditChecklist": [ "최고경영자는 정보보호 및 개인정보보호 처리에 관한 업무를 총괄하여 책임질 최고책임자를 공식적으로 지정하고 있는가?", @@ -77,7 +77,7 @@ "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", - "Subdomain": "1.1 관리체계", + "Subdomain": "1.1 관리체계 기반 마련", "Section": "1.1.3 조직 구성", "AuditChecklist": [ "정보보호 최고책임자 및 개인정보 보호책임자의 업무를 지원하고 조직의 정보보호 및 개인정보보호 활동을 체계적으로 이행하기 위하여 전문성을 갖춘 실무조직을 구성하여 운영하고 있는가?", @@ -112,7 +112,7 @@ "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", - "Subdomain": "1.1 관리체계", + "Subdomain": "1.1 관리체계 기반 마련", "Section": "1.1.4 범위 설정", "AuditChecklist": [ "조직의 핵심 서비스 및 개인정보 처리에 영향을 줄 수 있는 핵심자산을 포함하도록 관리체계 범위를 설정하고 있는가?", @@ -145,7 +145,7 @@ "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", - "Subdomain": "1.1 관리체계", + "Subdomain": "1.1 관리체계 기반 마련", "Section": "1.1.5 정책 수립", "AuditChecklist": [ "조직이 수행하는 모든 정보보호 및 개인정보보호 활동의 근거를 포함하는 최상위 수준의 정보보호 및 개인정보보호 정책을 수립하고 있는가?", @@ -180,7 +180,7 @@ "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", - "Subdomain": "1.1 관리체계", + "Subdomain": "1.1 관리체계 기반 마련", "Section": "1.1.6 자원 할당", "AuditChecklist": [ "정보보호 및 개인정보보호 분야별 전문성을 갖춘 인력을 확보하고 있는가?", @@ -206,11 +206,7 @@ "Id": "1.2.1", "Name": "정보자산 식별", "Description": "조직의 업무특성에 따라 정보자산 분류기준을 수립하여 관리체계 범위 내 모든 정보자산을 식별·분류하고, 중요도를 산정한 후 그 목록을 최신으로 관리하여야 한다.", - "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", @@ -403,10 +399,7 @@ "Id": "1.3.3", "Name": "운영현황 관리", "Description": "조직이 수립한 관리체계에 따라 상시적 또는 주기적으로 수행하여야 하는 운영활동 및 수행 내역은 식별 및 추적이 가능하도록 기록하여 관리하고, 경영진은 주기적으로 운영활동의 효과성을 확인하여 관리하여야 한다.", - "Checks": [ - "cloudwatch_log_metric_filter_aws_organizations_changes", - "codebuild_project_older_90_days" - ], + "Checks": [], "Attributes": [ { "Domain": "1. 관리체계 수립 및 운영", @@ -574,11 +567,7 @@ "Id": "2.1.2", "Name": "조직의 유지관리", "Description": "조직의 각 구성원에게 정보보호와 개인정보보호 관련 역할 및 책임을 할당하고, 그 활동을 평가할 수 있는 체계와 조직 및 조직의 구성원 간 상호 의사소통할 수 있는 체계를 수립하여 운영하여야 한다.", - "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "2. 보호대책 요구사항", @@ -617,18 +606,13 @@ "Name": "정보자산 관리", "Description": "정보자산의 용도와 중요도에 따른 취급 절차 및 보호대책을 수립·이행하고, 자산별 책임소재를 명확히 정의하여 관리하여야 한다.", "Checks": [ - "ec2_elastic_ip_unassigned", - "ec2_instance_older_than_specific_days", - "ecr_repositories_lifecycle_policy_enabled", + "fsx_file_system_copy_tags_to_backups_enabled", "fsx_file_system_copy_tags_to_volumes_enabled", "neptune_cluster_copy_tags_to_snapshots", - "organizations_account_part_of_organizations", - "organizations_delegated_administrators", - "organizations_scp_check_deny_regions", "organizations_tags_policies_enabled_and_attached", "rds_cluster_copy_tags_to_snapshots", "rds_instance_copy_tags_to_snapshots", - "resourceexplorer2_indexes_found" + "redshift_cluster_non_default_username" ], "Attributes": [ { @@ -658,10 +642,7 @@ "Id": "2.2.1", "Name": "주요 직무자 지정 및 관리", "Description": "개인정보 및 중요정보의 취급이나 주요 시스템 접근 등 주요 직무의 기준과 관리방안을 수립하고, 주요 직무자를 최소한으로 지정하여 그 목록을 최신으로 관리하여야 한다.", - "Checks": [ - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "2. 보호대책 요구사항", @@ -697,9 +678,7 @@ "Id": "2.2.2", "Name": "직무 분리", "Description": "권한 오·남용 등으로 인한 잠재적인 피해 예방을 위하여 직무 분리 기준을 수립하고 적용하여야 한다. 다만 불가피하게 직무 분리가 어려운 경우 별도의 보완대책을 마련하여 이행하여야 한다.", - "Checks": [ - "account_maintain_different_contact_details_to_security_billing_and_operations" - ], + "Checks": [], "Attributes": [ { "Domain": "2. 보호대책 요구사항", @@ -1105,7 +1084,7 @@ { "Id": "2.4.5 ", "Name": "보호구역 내 작업", - "Description": "보호구역 내에서의 비인가행위 및 권한 오·남용 등을 방지하기 위한 작업 절차를 수립 및이행하고, 작업 기록을 주기적으로 검토하여야 한다.", + "Description": "보호구역 내에서의 비인가행위 및 권한 오·남용 등을 방지하기 위한 작업 절차를 수립·이행하고, 작업 기록을 주기적으로 검토하여야 한다.", "Checks": [], "Attributes": [ { @@ -1132,7 +1111,7 @@ { "Id": "2.4.6", "Name": "반출입 기기 통제", - "Description": "보호구역 내 정보시스템, 모바일 기기, 저장매체 등에 대한 반출입 통제절차를 수립 및 이행하고 주기적으로 검토하여야 한다.", + "Description": "보호구역 내 정보시스템, 모바일 기기, 저장매체 등에 대한 반출입 통제절차를 수립·이행하고 주기적으로 검토하여야 한다.", "Checks": [], "Attributes": [ { @@ -1201,17 +1180,12 @@ "Checks": [ "accessanalyzer_enabled", "accessanalyzer_enabled_without_findings", - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", "account_security_questions_are_registered_in_the_aws_account", - "apigateway_restapi_authorizers_enabled", - "autoscaling_group_launch_configuration_requires_imdsv2", + "cognito_identity_pool_guest_access_disabled", "cognito_user_pool_deletion_protection_enabled", "cognito_user_pool_self_registration_disabled", - "config_recorder_using_aws_service_role", "ec2_instance_profile_attached", - "eventbridge_schema_registry_cross_account_access", + "iam_avoid_root_usage", "iam_aws_attached_policy_no_administrative_privileges", "iam_customer_attached_policy_no_administrative_privileges", "iam_customer_unattached_policy_no_administrative_privileges", @@ -1221,7 +1195,6 @@ "iam_inline_policy_no_full_access_to_cloudtrail", "iam_inline_policy_no_full_access_to_kms", "iam_no_custom_policy_permissive_role_assumption", - "iam_no_root_access_key", "iam_policy_allows_privilege_escalation", "iam_policy_attached_only_to_group_or_roles", "iam_policy_cloudshell_admin_not_attached", @@ -1232,7 +1205,10 @@ "iam_role_cross_service_confused_deputy_prevention", "iam_securityaudit_role_created", "iam_support_role_created", - "iam_user_administrator_access_policy" + "iam_user_administrator_access_policy", + "rds_cluster_default_admin", + "rds_instance_default_admin", + "redshift_cluster_non_default_database_name" ], "Attributes": [ { @@ -1267,8 +1243,6 @@ "Name": "사용자 식별", "Description": "사용자 계정은 사용자별로 유일하게 구분할 수 있도록 식별자를 할당하고 추측 가능한 식별자 사용을 제한하여야 하며, 동일한 식별자를 공유하여 사용하는 경우 그 사유와 타당성을 검토하여 책임자의 승인 및 책임추적성 확보 등 보완대책을 수립·이행하여야 한다.", "Checks": [ - "cognito_user_pool_advanced_security_enabled", - "ec2_instance_profile_attached", "efs_access_point_enforce_user_identity" ], "Attributes": [ @@ -1303,15 +1277,14 @@ "Description": "정보시스템과 개인정보 및 중요정보에 대한 사용자의 접근은 안전한 인증절차와 필요에 따라 강화된 인증방식을 적용하여야 한다. 또한 로그인 횟수 제한, 불법 로그인 시도 경고 등 비인가자 접근 통제방안을 수립·이행하여야 한다.", "Checks": [ "account_security_questions_are_registered_in_the_aws_account", - "apigateway_restapi_client_certificate_enabled", + "apigateway_restapi_authorizers_enabled", "apigateway_restapi_public_with_authorizer", "apigatewayv2_api_authorizers_enabled", "appstream_fleet_maximum_session_duration", "appstream_fleet_session_disconnect_timeout", "appstream_fleet_session_idle_disconnect_timeout", + "autoscaling_group_launch_configuration_requires_imdsv2", "cloudtrail_bucket_requires_mfa_delete", - "cloudwatch_log_metric_filter_authentication_failures", - "cloudwatch_log_metric_filter_sign_in_without_mfa", "cognito_user_pool_advanced_security_enabled", "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", @@ -1325,24 +1298,16 @@ "elasticache_redis_replication_group_auth_enabled", "iam_administrator_access_with_mfa", "iam_check_saml_providers_sts", - "iam_no_root_access_key", "iam_root_hardware_mfa_enabled", "iam_root_mfa_enabled", - "iam_rotate_access_key_90_days", - "iam_user_accesskey_unused", "iam_user_console_access_unused", "iam_user_hardware_mfa_enabled", "iam_user_mfa_enabled_console_access", - "iam_user_no_setup_initial_access_key", - "iam_user_two_active_access_key", "iam_user_with_temporary_credentials", "neptune_cluster_iam_authentication_enabled", - "opensearch_service_domains_internal_user_database_enabled", "opensearch_service_domains_use_cognito_authentication_for_kibana", - "organizations_account_part_of_organizations", "rds_cluster_iam_authentication_enabled", "rds_instance_iam_authentication_enabled", - "s3_bucket_cross_account_access", "s3_bucket_no_mfa_delete" ], "Attributes": [ @@ -1374,7 +1339,7 @@ { "Id": "2.5.4", "Name": "비밀번호 관리", - "Description": "법적 요구사항, 외부 위협요인 등을 고려하여 정보시스템 사용자 및 고객, 회원 등 정보주체(이용자)가 사용하는 비밀번호 관리절차를 수립·이행하여야 한다.", + "Description": "법적 요구사항, 외부 위협요인 등을 고려하여 정보시스템 사용자 및 고객, 회원 등 정보주체 (이용자)가 사용하는 비밀번호 관리절차를 수립·이행하여야 한다.", "Checks": [ "cognito_user_pool_password_policy_lowercase", "cognito_user_pool_password_policy_minimum_length_14", @@ -1423,11 +1388,6 @@ "Checks": [ "accessanalyzer_enabled", "accessanalyzer_enabled_without_findings", - "apigateway_restapi_authorizers_enabled", - "cloudwatch_log_metric_filter_root_usage", - "cognito_user_pool_self_registration_disabled", - "config_recorder_using_aws_service_role", - "ecs_task_definitions_no_privileged_containers", "iam_administrator_access_with_mfa", "iam_avoid_root_usage", "iam_aws_attached_policy_no_administrative_privileges", @@ -1445,17 +1405,12 @@ "iam_policy_no_full_access_to_cloudtrail", "iam_policy_no_full_access_to_kms", "iam_role_administratoraccess_policy", - "iam_role_cross_account_readonlyaccess_policy", "iam_root_hardware_mfa_enabled", "iam_root_mfa_enabled", "iam_securityaudit_role_created", "iam_support_role_created", "iam_user_administrator_access_policy", - "organizations_delegated_administrators", - "rds_cluster_default_admin", - "rds_instance_default_admin", - "sagemaker_notebook_instance_root_access_disabled", - "ses_identity_not_publicly_accessible" + "organizations_delegated_administrators" ], "Attributes": [ { @@ -1473,7 +1428,6 @@ "AuditEvidence": [ "특수권한 관련 지침", "특수권한 신청·승인 내역", - "특수권한자 목록", "특수권한 검토 내용" ], "NonComplianceCases": [ @@ -1492,25 +1446,9 @@ "Checks": [ "accessanalyzer_enabled", "accessanalyzer_enabled_without_findings", - "apigateway_restapi_authorizers_enabled", - "appstream_fleet_maximum_session_duration", - "appstream_fleet_session_disconnect_timeout", - "appstream_fleet_session_idle_disconnect_timeout", - "autoscaling_group_launch_configuration_requires_imdsv2", - "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_group_not_publicly_accessible", - "cloudwatch_log_metric_filter_policy_changes", - "cognito_identity_pool_guest_access_disabled", - "cognito_user_pool_advanced_security_enabled", - "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", - "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", - "cognito_user_pool_client_prevent_user_existence_errors", - "cognito_user_pool_client_token_revocation_enabled", - "cognito_user_pool_self_registration_disabled", "config_recorder_using_aws_service_role", "dynamodb_table_cross_account_access", "ec2_instance_internet_facing_with_instance_profile", - "ec2_instance_managed_by_ssm", "ec2_instance_profile_attached", "eventbridge_bus_cross_account_access", "eventbridge_schema_registry_cross_account_access", @@ -1538,7 +1476,6 @@ "s3_bucket_policy_public_write_access", "s3_bucket_public_list_acl", "s3_bucket_public_write_acl", - "ses_identity_not_publicly_accessible", "sns_topics_not_publicly_accessible", "sqs_queues_not_publicly_accessible", "ssm_documents_set_as_public", @@ -1550,7 +1487,7 @@ "Subdomain": "2.5 인증 및 권한관리", "Section": "2.5.6 접근권한 검토", "AuditChecklist": [ - "정보시스템과 개인정보 및 중요정보에 대한 사용자 계정 및 접근권한 생성·등록·부여· 이용·변경·말소 등의 이력을 남기고 있는가?", + "정보시스템과 개인정보 및 중요정보에 대한 사용자 계정 및 접근권한 생성·등록·부여·이용·변경·말소 등의 이력을 남기고 있는가?", "정보시스템과 개인정보 및 중요정보에 대한 사용자 계정 및 접근권한의 적정성 검토 기준, 검토주체, 검토방법, 주기 등을 수립하여 정기적 검토를 이행하고 있는가?", "접근권한 검토 결과 접근권한 과다 부여, 권한부여 절차 미준수, 권한 오·남용 등 문제점이 발견된 경우 그에 따른 조치절차를 수립·이행하고 있는가?" ], @@ -1576,27 +1513,22 @@ "Name": "네트워크 접근", "Description": "네트워크에 대한 비인가 접근을 통제하기 위하여 IP관리, 단말인증 등 관리절차를 수립 및이행하고, 업무목적 및 중요도에 따라 네트워크 분리(DMZ, 서버팜, DB존, 개발존 등)와 접근통제를 적용하여야 한다.", "Checks": [ - "apigateway_restapi_authorizers_enabled", - "apigateway_restapi_client_certificate_enabled", "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", "apigateway_restapi_waf_acl_attached", "appstream_fleet_default_internet_access_disabled", "autoscaling_group_launch_configuration_no_public_ip", "awslambda_function_inside_vpc", "awslambda_function_not_publicly_accessible", - "cloudfront_distributions_default_root_object", "cloudfront_distributions_geo_restrictions_enabled", "cloudfront_distributions_s3_origin_access_control", "cloudfront_distributions_using_waf", "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", - "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", - "cloudwatch_log_metric_filter_security_group_changes", + "cloudwatch_log_group_not_publicly_accessible", "cognito_user_pool_waf_acl_attached", + "dms_endpoint_ssl_enabled", "dms_instance_no_public_access", "documentdb_cluster_public_snapshot", - "dynamodb_table_cross_account_access", + "ec2_elastic_ip_shodan", "ec2_instance_internet_facing_with_instance_profile", "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_cifs_exposed_to_internet", @@ -1641,68 +1573,50 @@ "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", "ec2_securitygroup_allow_wide_open_public_ipv4", "ec2_securitygroup_default_restrict_traffic", - "ec2_securitygroup_from_launch_wizard", - "ec2_securitygroup_not_used", - "ec2_securitygroup_with_many_ingress_egress_rules", "ec2_transitgateway_auto_accept_vpc_attachments", "ecr_repositories_not_publicly_accessible", "ecs_service_no_assign_public_ip", "ecs_task_set_no_assign_public_ip", "efs_mount_target_not_publicly_accessible", - "efs_not_publicly_accessible", "eks_cluster_network_policy_enabled", "eks_cluster_not_publicly_accessible", "eks_cluster_private_nodes_enabled", "elasticache_cluster_uses_public_subnet", "elb_internet_facing", "elbv2_internet_facing", - "elbv2_listeners_underneath", "elbv2_waf_acl_attached", "emr_cluster_account_public_block_enabled", "emr_cluster_master_nodes_no_public_ip", "emr_cluster_publicly_accesible", - "eventbridge_bus_exposed", - "glue_data_catalogs_not_publicly_accessible", + "glacier_vaults_policy_public_access", "kafka_cluster_is_public", - "kafka_cluster_unrestricted_access_disabled", "lightsail_database_public", "lightsail_instance_public", - "lightsail_static_ip_unused", - "neptune_cluster_public_snapshot", "neptune_cluster_uses_public_subnet", - "networkfirewall_deletion_protection", - "networkfirewall_in_all_vpc", - "networkfirewall_multi_az", - "networkfirewall_policy_default_action_fragmented_packets", - "networkfirewall_policy_default_action_full_packets", - "networkfirewall_policy_rule_group_associated", "opensearch_service_domains_not_publicly_accessible", - "rds_snapshots_public_access", + "rds_cluster_non_default_port", "rds_instance_inside_vpc", + "rds_instance_no_public_access", + "rds_instance_non_default_port", "redshift_cluster_enhanced_vpc_routing", "redshift_cluster_public_access", "route53_dangling_ip_subdomain_takeover", "s3_access_point_public_access_block", + "s3_account_level_public_access_blocks", + "s3_bucket_level_public_access_block", + "s3_bucket_public_access", + "s3_multi_region_access_point_public_access_block", "sagemaker_models_network_isolation_enabled", "sagemaker_models_vpc_settings_configured", "sagemaker_notebook_instance_vpc_settings_configured", "sagemaker_notebook_instance_without_direct_internet_access_configured", "sagemaker_training_jobs_network_isolation_enabled", "sagemaker_training_jobs_vpc_settings_configured", - "sqs_queues_server_side_encryption_enabled", "vpc_endpoint_connections_trust_boundaries", "vpc_endpoint_for_ec2_enabled", "vpc_peering_routing_tables_with_least_privilege", "vpc_subnet_no_public_ip_by_default", "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", - "waf_global_rule_with_conditions", - "waf_global_rulegroup_not_empty", - "waf_global_webacl_with_rules", - "waf_regional_rule_with_conditions", - "waf_regional_rulegroup_not_empty", - "waf_regional_webacl_with_rules", - "wafv2_webacl_with_rules", "workspaces_vpc_2private_1public_subnets_nat" ], "Attributes": [ @@ -1741,24 +1655,14 @@ "Name": "정보시스템 접근", "Description": "서버, 네트워크시스템 등 정보시스템에 접근을 허용하는 사용자, 접근제한 방식, 안전한 접근수단 등을 정의하여 통제하여야 한다.", "Checks": [ - "apigateway_restapi_client_certificate_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", "apigateway_restapi_waf_acl_attached", - "apigatewayv2_api_authorizers_enabled", "athena_workgroup_enforce_configuration", - "autoscaling_group_launch_configuration_requires_imdsv2", - "awslambda_function_inside_vpc", - "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", - "awslambda_function_not_publicly_accessible", - "cloudfront_distributions_s3_origin_access_control", + "awslambda_function_url_cors_policy", + "awslambda_function_url_public", + "cloudfront_distributions_default_root_object", + "cloudfront_distributions_using_waf", "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_group_not_publicly_accessible", - "cognito_identity_pool_guest_access_disabled", - "cognito_user_pool_client_token_revocation_enabled", - "dms_instance_no_public_access", - "documentdb_cluster_public_snapshot", - "dynamodb_table_cross_account_access", + "cognito_user_pool_waf_acl_attached", "ec2_ami_public", "ec2_ebs_public_snapshot", "ec2_ebs_snapshot_account_block_public_access", @@ -1766,70 +1670,39 @@ "ec2_instance_imdsv2_enabled", "ec2_instance_internet_facing_with_instance_profile", "ec2_instance_managed_by_ssm", - "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_cifs_exposed_to_internet", + "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", + "ec2_instance_port_kafka_exposed_to_internet", + "ec2_instance_port_kerberos_exposed_to_internet", + "ec2_instance_port_ldap_exposed_to_internet", "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", "ec2_instance_port_ssh_exposed_to_internet", "ec2_instance_port_telnet_exposed_to_internet", - "ec2_networkacl_allow_ingress_any_port", - "ec2_networkacl_allow_ingress_tcp_port_22", - "ec2_networkacl_allow_ingress_tcp_port_3389", - "ec2_networkacl_unused", "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", "ec2_securitygroup_allow_ingress_from_internet_to_any_port", "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", - "ecr_repositories_not_publicly_accessible", - "ecs_service_no_assign_public_ip", - "ecs_task_definitions_host_namespace_not_shared", - "ecs_task_definitions_host_networking_mode_users", "ecs_task_definitions_no_privileged_containers", - "ecs_task_set_no_assign_public_ip", "efs_access_point_enforce_root_directory", "efs_access_point_enforce_user_identity", - "efs_mount_target_not_publicly_accessible", "efs_not_publicly_accessible", - "eks_cluster_network_policy_enabled", - "eks_cluster_not_publicly_accessible", - "eks_cluster_private_nodes_enabled", - "elasticache_cluster_uses_public_subnet", - "elasticache_redis_replication_group_auth_enabled", - "emr_cluster_account_public_block_enabled", - "emr_cluster_master_nodes_no_public_ip", - "emr_cluster_publicly_accesible", + "elbv2_waf_acl_attached", + "eventbridge_bus_cross_account_access", "eventbridge_bus_exposed", - "glacier_vaults_policy_public_access", + "eventbridge_schema_registry_cross_account_access", "glue_data_catalogs_not_publicly_accessible", - "guardduty_lambda_protection_enabled", - "guardduty_s3_protection_enabled", "kafka_cluster_is_public", "kafka_cluster_unrestricted_access_disabled", - "lightsail_instance_public", - "lightsail_static_ip_unused", "neptune_cluster_public_snapshot", "opensearch_service_domains_not_publicly_accessible", "opensearch_service_domains_use_cognito_authentication_for_kibana", + "rds_snapshots_public_access", "s3_access_point_public_access_block", "s3_account_level_public_access_blocks", "s3_bucket_acl_prohibited", @@ -1840,7 +1713,10 @@ "s3_bucket_public_list_acl", "s3_bucket_public_write_acl", "s3_multi_region_access_point_public_access_block", - "ssm_documents_set_as_public" + "sagemaker_notebook_instance_root_access_disabled", + "ses_identity_not_publicly_accessible", + "ssm_documents_set_as_public", + "vpc_endpoint_connections_trust_boundaries" ], "Attributes": [ { @@ -1878,24 +1754,8 @@ "Name": "응용프로그램 접근", "Description": "사용자별 업무 및 접근 정보의 중요도 등에 따라 응용프로그램 접근권한을 제한하고, 불필요한 정보 또는 중요정보 노출을 최소화할 수 있도록 기준을 수립하여 적용하여야 한다.", "Checks": [ - "apigateway_restapi_authorizers_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", - "apigatewayv2_api_authorizers_enabled", - "awslambda_function_url_cors_policy", - "awslambda_function_url_public", - "cloudfront_distributions_default_root_object", - "codeartifact_packages_external_public_publishing_disabled", - "cognito_user_pool_waf_acl_attached", - "ec2_ami_public", "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ecr_repositories_not_publicly_accessible", - "ecs_task_definitions_host_namespace_not_shared", - "ecs_task_definitions_host_networking_mode_users", - "eks_cluster_network_policy_enabled" + "opensearch_service_domains_use_cognito_authentication_for_kibana" ], "Attributes": [ { @@ -1928,7 +1788,7 @@ "사례 1 : 응용프로그램의 개인정보 처리화면 중 일부 화면의 권한 제어 기능에 오류가 존재하여 개인정보 열람 권한이 없는 사용자에게도 개인정보가 노출되고 있는 경우", "사례 2 : 응용프로그램의 관리자 페이지가 외부인터넷에 오픈되어 있으면서 안전한 인증수단이 적용되어 있지 않은 경우", "사례 3 : 응용프로그램에 대하여 타당한 사유 없이 세션 타임아웃 또는 동일 사용자 계정의 동시 접속을 제한하고 있지 않은 경우", - "사례 4 : 응용프로그램을 통하여 개인정보를 다운로드받는 경우 해당 파일 내에 주민등록번호 등 업무상 불필요한 정보가 과도하게 포함되어 있는 경우,", + "사례 4 : 응용프로그램을 통하여 개인정보를 다운로드받는 경우 해당 파일 내에 주민등록번호 등 업무상 불필요한 정보가 과도하게 포함되어 있는 경우", "사례 5 : 응용프로그램의 개인정보 조회화면에서 like 검색을 과도하게 허용하고 있어, 모든 사용자가 본인의 업무 범위를 초과하여 성씨만으로도 전체 고객 정보를 조회할 수 있는 경우", "사례 6 : 개인정보 표시제한 조치 기준이 마련되어 있지 않거나 이를 준수하지 않는 등의 사유로 동일한 개인정보 항목에 대하여 개인정보처리시스템 화면별로 서로 다른 마스킹 기준이 적용된 경우", "사례 7 : 개인정보처리시스템의 화면상에는 개인정보가 마스킹되어 표시되어 있으나, 웹브라우저 소스보기를 통하여 마스킹되지 않은 전체 개인정보가 노출되는 경우" @@ -1944,7 +1804,6 @@ "dms_endpoint_mongodb_authentication_enabled", "dms_endpoint_neptune_iam_authorization_enabled", "dms_endpoint_ssl_enabled", - "documentdb_cluster_public_snapshot", "dynamodb_table_cross_account_access", "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_memcached_exposed_to_internet", @@ -1954,6 +1813,10 @@ "ec2_instance_port_postgresql_exposed_to_internet", "ec2_instance_port_redis_exposed_to_internet", "ec2_instance_port_sqlserver_exposed_to_internet", + "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", @@ -1961,25 +1824,17 @@ "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", - "guardduty_rds_protection_enabled", + "elasticache_redis_replication_group_auth_enabled", "lightsail_database_public", "neptune_cluster_iam_authentication_enabled", - "neptune_cluster_uses_public_subnet", + "neptune_cluster_public_snapshot", "opensearch_service_domains_internal_user_database_enabled", "rds_cluster_iam_authentication_enabled", "rds_cluster_non_default_port", - "rds_cluster_storage_encrypted", "rds_instance_iam_authentication_enabled", "rds_instance_no_public_access", "rds_instance_non_default_port", - "rds_instance_storage_encrypted", - "rds_instance_transport_encrypted", - "rds_snapshots_public_access", - "redshift_cluster_encrypted_at_rest", "redshift_cluster_enhanced_vpc_routing", - "redshift_cluster_in_transit_encryption_enabled", - "redshift_cluster_non_default_database_name", - "redshift_cluster_non_default_username", "redshift_cluster_public_access" ], "Attributes": [ @@ -2054,7 +1909,6 @@ "appstream_fleet_maximum_session_duration", "appstream_fleet_session_disconnect_timeout", "appstream_fleet_session_idle_disconnect_timeout", - "autoscaling_group_launch_configuration_requires_imdsv2", "ec2_instance_port_cifs_exposed_to_internet", "ec2_instance_port_ftp_exposed_to_internet", "ec2_instance_port_rdp_exposed_to_internet", @@ -2062,12 +1916,13 @@ "ec2_instance_port_telnet_exposed_to_internet", "ec2_networkacl_allow_ingress_tcp_port_22", "ec2_networkacl_allow_ingress_tcp_port_3389", + "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", + "ec2_securitygroup_allow_ingress_from_internet_to_any_port", + "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", - "vpc_vpn_connection_tunnels_up", - "workspaces_volume_encryption_enabled", "workspaces_vpc_2private_1public_subnets_nat" ], "Attributes": [ @@ -2107,59 +1962,7 @@ "Id": "2.6.7", "Name": "인터넷 접속 통제", "Description": "인터넷을 통한 정보 유출, 악성코드 감염, 내부망 침투 등을 예방하기 위하여 주요 정보시스템, 주요 직무 수행 및 개인정보 취급 단말기 등에 대한 인터넷 접속 또는 서비스(P2P, 웹하드, 메신저 등)를 제한하는 등 인터넷 접속 통제 정책을 수립·이행하여야 한다.", - "Checks": [ - "apigateway_restapi_waf_acl_attached", - "appstream_fleet_default_internet_access_disabled", - "autoscaling_group_launch_configuration_no_public_ip", - "awslambda_function_not_publicly_accessible", - "awslambda_function_url_cors_policy", - "awslambda_function_url_public", - "cloudfront_distributions_using_waf", - "dms_instance_no_public_access", - "ec2_elastic_ip_shodan", - "ec2_instance_port_cassandra_exposed_to_internet", - "ec2_instance_port_cifs_exposed_to_internet", - "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", - "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", - "ec2_instance_port_ssh_exposed_to_internet", - "ec2_instance_port_telnet_exposed_to_internet", - "ec2_instance_public_ip", - "ecs_service_no_assign_public_ip", - "elb_internet_facing", - "elbv2_internet_facing", - "emr_cluster_account_public_block_enabled", - "emr_cluster_master_nodes_no_public_ip", - "emr_cluster_publicly_accesible", - "eventbridge_bus_exposed", - "glue_data_catalogs_not_publicly_accessible", - "kafka_cluster_is_public", - "kafka_cluster_unrestricted_access_disabled", - "neptune_cluster_public_snapshot", - "networkfirewall_deletion_protection", - "networkfirewall_in_all_vpc", - "networkfirewall_multi_az", - "opensearch_service_domains_not_publicly_accessible", - "route53_dangling_ip_subdomain_takeover", - "sagemaker_notebook_instance_without_direct_internet_access_configured", - "vpc_endpoint_connections_trust_boundaries", - "vpc_endpoint_for_ec2_enabled", - "vpc_peering_routing_tables_with_least_privilege", - "vpc_subnet_no_public_ip_by_default", - "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", - "workspaces_vpc_2private_1public_subnets_nat" - ], + "Checks": [], "Attributes": [ { "Domain": "2. 보호대책 요구사항", @@ -2198,8 +2001,8 @@ "Checks": [ "acm_certificates_expiration_check", "acm_certificates_with_secure_key_algorithms", - "apigateway_restapi_authorizers_enabled", "apigateway_restapi_cache_encrypted", + "apigateway_restapi_client_certificate_enabled", "athena_workgroup_encryption", "awslambda_function_no_secrets_in_code", "awslambda_function_no_secrets_in_variables", @@ -2211,7 +2014,6 @@ "cloudfront_distributions_https_sni_enabled", "cloudfront_distributions_origin_traffic_encrypted", "cloudfront_distributions_using_deprecated_ssl_protocols", - "cloudwatch_log_group_no_secrets_in_logs", "codebuild_project_no_secrets_in_variables", "codebuild_project_s3_logs_encrypted", "codebuild_project_source_repo_url_no_sensitive_credentials", @@ -2229,7 +2031,6 @@ "ec2_launch_template_no_secrets", "ecs_task_definitions_no_environment_secrets", "efs_encryption_at_rest_enabled", - "eks_cluster_kms_cmk_encryption_in_secrets_enabled", "elasticache_redis_cluster_in_transit_encryption_enabled", "elasticache_redis_cluster_rest_encryption_enabled", "elb_insecure_ssl_ciphers", @@ -2248,7 +2049,7 @@ "glue_etl_jobs_cloudwatch_logs_encryption_enabled", "glue_etl_jobs_job_bookmark_encryption_enabled", "glue_ml_transform_encrypted_at_rest", - "kafka_cluster_encryption_at_rest_uses_cmk", + "iam_no_expired_server_certificates_stored", "kafka_cluster_in_transit_encryption_enabled", "kafka_cluster_mutual_tls_authentication_enabled", "kafka_connector_in_transit_encryption_enabled", @@ -2259,6 +2060,7 @@ "opensearch_service_domains_https_communications_enforced", "opensearch_service_domains_node_to_node_encryption_enabled", "rds_cluster_storage_encrypted", + "rds_instance_certificate_expiration", "rds_instance_storage_encrypted", "rds_instance_transport_encrypted", "rds_snapshots_encrypted", @@ -2268,11 +2070,11 @@ "s3_bucket_secure_transport_policy", "sagemaker_notebook_instance_encryption_enabled", "sagemaker_training_jobs_intercontainer_encryption_enabled", - "sagemaker_training_jobs_volume_and_output_encryption_enabled", "sns_subscription_not_using_http_endpoints", "sqs_queues_server_side_encryption_enabled", "ssm_document_secrets", - "transfer_server_in_transit_encryption_enabled" + "transfer_server_in_transit_encryption_enabled", + "workspaces_volume_encryption_enabled" ], "Attributes": [ { @@ -2308,40 +2110,30 @@ "Name": "암호키 관리", "Description": "암호키의 안전한 생성·이용·보관·배포·파기를 위한 관리 절차를 수립·이행하고, 필요 시 복구방안을 마련하여야 한다.", "Checks": [ - "acm_certificates_expiration_check", - "acm_certificates_transparency_logs_enabled", - "athena_workgroup_encryption", "backup_vaults_encrypted", "bedrock_model_invocation_logs_encryption_enabled", - "cloudfront_distributions_custom_ssl_certificate", - "cloudfront_distributions_https_enabled", - "cloudfront_distributions_https_sni_enabled", - "cloudfront_distributions_origin_traffic_encrypted", - "cloudfront_distributions_using_deprecated_ssl_protocols", "cloudtrail_kms_encryption_enabled", "cloudwatch_log_group_kms_encryption_enabled", - "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", - "dms_endpoint_ssl_enabled", "dynamodb_tables_kms_cmk_encryption_enabled", "eks_cluster_kms_cmk_encryption_in_secrets_enabled", - "iam_no_expired_server_certificates_stored", + "iam_no_root_access_key", "iam_rotate_access_key_90_days", "iam_user_accesskey_unused", "iam_user_no_setup_initial_access_key", "iam_user_two_active_access_key", + "kafka_cluster_encryption_at_rest_uses_cmk", "kms_cmk_are_used", "kms_cmk_not_deleted_unintentionally", "kms_cmk_rotation_enabled", "kms_key_not_publicly_accessible", - "rds_instance_certificate_expiration", "s3_bucket_kms_encryption", + "sagemaker_training_jobs_volume_and_output_encryption_enabled", "secretsmanager_automatic_rotation_enabled", "secretsmanager_not_publicly_accessible", "secretsmanager_secret_rotated_periodically", "secretsmanager_secret_unused", "sns_topics_kms_encryption_at_rest_enabled", - "storagegateway_fileshare_encryption_enabled", - "workspaces_volume_encryption_enabled" + "storagegateway_fileshare_encryption_enabled" ], "Attributes": [ { @@ -2477,7 +2269,7 @@ "Section": "2.8.4 시험 데이터 보안", "AuditChecklist": [ "정보시스템의 개발 및 시험 과정에서 실제 운영 데이터의 사용을 제한하고 있는가?", - "불가피하게 운영데이터를 시험 환경에서 사용할 경우 책임자 승인, 접근 및 유출 모니터링, 시험 후 데이터 삭제 등의 통제 절차를 수립·이행하고 있는가?" + "불가피하게 운영데이터를 시험 환경에서 사용할 경우 책임자 승인, 접근 및 유출 모니터링, 시험 후 데이터 삭제 등의 통제 절차를 수립·이행하고 있는가?" ], "RelatedRegulations": [], "AuditEvidence": [ @@ -2499,8 +2291,7 @@ "Name": "소스 프로그램 관리", "Description": "소스 프로그램은 인가된 사용자만이 접근할 수 있도록 관리하고, 운영환경에 보관하지 않는 것을 원칙으로 하여야 한다.", "Checks": [ - "codeartifact_packages_external_public_publishing_disabled", - "ecr_repositories_tag_immutability" + "codeartifact_packages_external_public_publishing_disabled" ], "Attributes": [ { @@ -2587,7 +2378,6 @@ "Name": "성능 및 장애관리", "Description": "정보시스템의 가용성 보장을 위하여 성능 및 용량 요구사항을 정의하고 현황을 지속적으로 모니터링하여야 하며, 장애 발생 시 효과적으로 대응하기 위한 탐지·기록·분석·복구·보고 등의 절차를 수립·관리하여야 한다.", "Checks": [ - "acm_certificates_expiration_check", "apigateway_restapi_tracing_enabled", "autoscaling_group_capacity_rebalance_enabled", "autoscaling_group_elb_health_check_enabled", @@ -2598,14 +2388,18 @@ "cloudfront_distributions_s3_origin_non_existent_bucket", "directconnect_connection_redundancy", "directconnect_virtual_interface_redundancy", - "dlm_ebs_snapshot_lifecycle_policy_exists", + "directoryservice_directory_snapshots_limit", "dms_instance_multi_az_enabled", "documentdb_cluster_deletion_protection", "documentdb_cluster_multi_az_enabled", "dynamodb_accelerator_cluster_multi_az", "dynamodb_table_autoscaling_enabled", "dynamodb_table_deletion_protection_enabled", + "ec2_elastic_ip_unassigned", "ec2_instance_detailed_monitoring_enabled", + "ec2_instance_older_than_specific_days", + "ec2_instance_paravirtual_type", + "ecr_repositories_lifecycle_policy_enabled", "ecs_cluster_container_insights_enabled", "ecs_task_definitions_containers_readonly_access", "ecs_task_definitions_logging_block_mode", @@ -2618,10 +2412,11 @@ "elbv2_cross_zone_load_balancing_enabled", "elbv2_deletion_protection", "elbv2_is_in_multiple_az", + "eventbridge_global_endpoint_event_replication_enabled", "fsx_windows_file_system_multi_az_enabled", - "iam_no_expired_server_certificates_stored", "kafka_cluster_enhanced_monitoring_enabled", "kms_cmk_not_deleted_unintentionally", + "lightsail_static_ip_unused", "mq_broker_active_deployment_mode", "mq_broker_cluster_deployment_mode", "neptune_cluster_deletion_protection", @@ -2632,21 +2427,13 @@ "opensearch_service_domains_fault_tolerant_master_nodes", "rds_cluster_deletion_protection", "rds_cluster_multi_az", - "rds_instance_certificate_expiration", "rds_instance_deletion_protection", - "rds_instance_deprecated_engine_version", + "rds_instance_enhanced_monitoring_enabled", "rds_instance_multi_az", "redshift_cluster_multi_az_enabled", + "resourceexplorer2_indexes_found", "s3_bucket_cross_region_replication", - "s3_bucket_no_mfa_delete", - "s3_bucket_object_lock", - "s3_bucket_object_versioning", "sagemaker_endpoint_config_prod_variant_instances", - "shield_advanced_protection_in_classic_load_balancers", - "shield_advanced_protection_in_global_accelerators", - "shield_advanced_protection_in_internet_facing_load_balancers", - "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", "vpc_different_regions", "vpc_endpoint_multi_az_enabled", "vpc_subnet_different_az", @@ -2659,7 +2446,7 @@ "Section": "2.9.2 성능 및 장애관리", "AuditChecklist": [ "정보시스템의 가용성 보장을 위하여 성능 및 용량을 지속적으로 모니터링할 수 있는 절차를 수립·이행하고 있는가?", - "정보시스템 성능 및 용량 요구사항(임계치)을 초과하는 경우에 대한 대응절차를 수립 및 이행하고 있는가?", + "정보시스템 성능 및 용량 요구사항(임계치)을 초과하는 경우에 대한 대응절차를 수립·이행하고 있는가?", "정보시스템 장애를 즉시 인지하고 대응하기 위한 절차를 수립·이행하고 있는가?", "장애 발생 시 절차에 따라 조치하고 장애조치보고서 등을 통하여 장애조치내역을 기록하여 관리하고 있는가?", "심각도가 높은 장애의 경우 원인분석을 통한 재발방지 대책을 마련하고 있는가?" @@ -2688,9 +2475,9 @@ "backup_plans_exist", "backup_recovery_point_encrypted", "backup_reportplans_exist", + "backup_vaults_encrypted", "backup_vaults_exist", "cloudfront_distributions_multiple_origin_failover_configured", - "directoryservice_directory_snapshots_limit", "dlm_ebs_snapshot_lifecycle_policy_exists", "documentdb_cluster_backup_enabled", "dynamodb_table_protected_by_backup_plan", @@ -2699,22 +2486,16 @@ "ec2_ebs_volume_snapshots_exists", "efs_have_backup_enabled", "elasticache_redis_cluster_backup_enabled", - "fsx_file_system_copy_tags_to_backups_enabled", "lightsail_instance_automated_snapshots", "neptune_cluster_backup_enabled", - "neptune_cluster_copy_tags_to_snapshots", - "neptune_cluster_public_snapshot", - "neptune_cluster_snapshot_encrypted", "rds_cluster_backtrack_enabled", - "rds_cluster_copy_tags_to_snapshots", "rds_cluster_protected_by_backup_plan", "rds_instance_backup_enabled", - "rds_instance_copy_tags_to_snapshots", "rds_instance_protected_by_backup_plan", - "rds_snapshots_encrypted", - "rds_snapshots_public_access", "redshift_cluster_automated_snapshot", - "s3_bucket_lifecycle_enabled" + "s3_bucket_lifecycle_enabled", + "s3_bucket_object_lock", + "s3_bucket_object_versioning" ], "Attributes": [ { @@ -2723,8 +2504,8 @@ "Section": "2.9.3 백업 및 복구관리", "AuditChecklist": [ "백업 대상, 주기, 방법, 절차 등이 포함된 백업 및 복구절차를 수립·이행하고 있는가?", - "백업된 정보의 완전성과 정확성, 복구절차의 적절성을 확인하기 위하여 정기적으로 복구 테스트를 실시하고 있는가?", - "중요정보가 저장된 백업매체의 경우 재해·재난에 대처할 수 있도록 백업매체를 물리적으로 떨어진 장소에 소산하고 있는가?" + "백업된 정보의 완전성과 정확성, 복구절차의 적절성을 확인하기 위하여 정기적으로 복구 테스트를 실시하고 있는가?", + "중요정보가 저장된 백업매체의 경우 재해·재난에 대처할 수 있도록 백업매체를 물리적으로 떨어진 장소에 소산하고 있는가?" ], "RelatedRegulations": [ "개인정보 보호법 제29조(안전조치 의무)", @@ -2756,7 +2537,6 @@ "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", "bedrock_model_invocation_logging_enabled", "bedrock_model_invocation_logs_encryption_enabled", - "cloudformation_stack_outputs_find_secrets", "cloudfront_distributions_logging_enabled", "cloudtrail_bucket_requires_mfa_delete", "cloudtrail_cloudwatch_logging_enabled", @@ -2776,14 +2556,11 @@ "cloudwatch_changes_to_network_gateways_alarm_configured", "cloudwatch_changes_to_network_route_tables_alarm_configured", "cloudwatch_changes_to_vpcs_alarm_configured", - "cloudwatch_log_group_kms_encryption_enabled", "cloudwatch_log_group_no_critical_pii_in_logs", "cloudwatch_log_group_no_secrets_in_logs", - "cloudwatch_log_group_not_publicly_accessible", "cloudwatch_log_group_retention_policy_specific_days_enabled", "codebuild_project_logging_enabled", "codebuild_project_s3_logs_encrypted", - "config_recorder_all_regions_enabled", "datasync_task_logging_enabled", "directoryservice_directory_log_forwarding_enabled", "directoryservice_directory_monitor_notifications", @@ -2795,22 +2572,14 @@ "elasticbeanstalk_environment_cloudwatch_logging_enabled", "elb_logging_enabled", "elbv2_logging_enabled", - "eventbridge_global_endpoint_event_replication_enabled", - "glue_development_endpoints_cloudwatch_logs_encryption_enabled", - "glue_etl_jobs_cloudwatch_logs_encryption_enabled", "glue_etl_jobs_logging_enabled", - "kafka_cluster_enhanced_monitoring_enabled", + "guardduty_eks_audit_log_enabled", "mq_broker_logging_enabled", "neptune_cluster_integration_cloudwatch_logs", "networkfirewall_logging_enabled", "opensearch_service_domains_audit_logging_enabled", "opensearch_service_domains_cloudwatch_logging_enabled", - "rds_cluster_critical_event_subscription", "rds_cluster_integration_cloudwatch_logs", - "rds_instance_critical_event_subscription", - "rds_instance_enhanced_monitoring_enabled", - "rds_instance_event_subscription_parameter_groups", - "rds_instance_event_subscription_security_groups", "rds_instance_integration_cloudwatch_logs", "redshift_cluster_audit_logging", "route53_public_hosted_zones_cloudwatch_logging_enabled", @@ -2862,7 +2631,7 @@ "Subdomain": "2.9 시스템 및 서비스 운영관리", "Section": "2.9.5 로그 및 접속기록 점검", "AuditChecklist": [ - "정보시스템 관련 오류, 오·남용(비인가접속, 과다조회 등), 부정행위 등 이상징후를 인지할 수 있도록 로그 검토 주기, 대상, 방법 등을 포함한 로그 검토 및 모니터링 절차를 수립·이행하고 있는가?", + "정보시스템 관련 오류, 오·남용(비인가접속, 과다조회 등), 부정행위 등 이상징후를 인지할 수 있도록 로그 검토 주기, 대상, 방법 등을 포함한 로그 검토 및 모니터링 절차를 수립·이행하고 있는가?", "로그 검토 및 모니터링 결과를 책임자에게 보고하고 이상징후 발견 시 절차에 따라 대응하고 있는가?", "개인정보처리시스템의 접속기록은 관련 법령에서 정한 주기에 따라 정기적으로 점검하고 있는가?" ], @@ -2954,8 +2723,6 @@ "Description": "보안시스템 유형별로 관리자 지정, 최신 정책 업데이트, 룰셋 변경, 이벤트 모니터링 등의 운영절차를 수립·이행하고 보안시스템별 정책적용 현황을 관리하여야 한다.", "Checks": [ "apigateway_restapi_waf_acl_attached", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", "cloudfront_distributions_using_waf", "cloudtrail_bucket_requires_mfa_delete", "cloudtrail_cloudwatch_logging_enabled", @@ -3001,8 +2768,6 @@ "dms_instance_minor_version_upgrade_enabled", "dms_instance_multi_az_enabled", "dms_instance_no_public_access", - "ec2_client_vpn_endpoint_connection_logging_enabled", - "ec2_instance_managed_by_ssm", "elbv2_waf_acl_attached", "fms_policy_compliant", "guardduty_centrally_managed", @@ -3037,7 +2802,6 @@ "shield_advanced_protection_in_internet_facing_load_balancers", "shield_advanced_protection_in_route53_hosted_zones", "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", "waf_global_rule_with_conditions", "waf_global_rulegroup_not_empty", "waf_global_webacl_logging_enabled", @@ -3057,7 +2821,7 @@ "AuditChecklist": [ "조직에서 운영하고 있는 보안시스템에 대한 운영절차를 수립·이행하고 있는가?", "보안시스템 관리자 등 접근이 허용된 인원을 최소화하고 비인가자의 접근을 엄격하게 통제하고 있는가?", - "보안시스템별로 정책의 신규 등록, 변경, 삭제 등을 위한 공식적인 절차를 수립 및 이행하고 있는가?", + "보안시스템별로 정책의 신규 등록, 변경, 삭제 등을 위한 공식적인 절차를 수립·이행하고 있는가?", "보안시스템의 예외 정책 등록에 대하여 절차에 따라 관리하고 있으며, 예외 정책 사용자에 대하여 최소한의 권한으로 관리하고 있는가?", "보안시스템에 설정된 정책의 타당성 여부를 주기적으로 검토하고 있는가?", "개인정보처리시스템에 대한 불법적인 접근 및 개인정보 유출 방지를 위하여 관련 법령에서 정한 기능을 수행하는 보안시스템을 설치하여 운영하고 있는가?" @@ -3105,10 +2869,8 @@ "apigateway_restapi_logging_enabled", "apigateway_restapi_public", "apigateway_restapi_public_with_authorizer", - "apigateway_restapi_tracing_enabled", "apigateway_restapi_waf_acl_attached", "apigatewayv2_api_access_logging_enabled", - "apigatewayv2_api_authorizers_enabled", "appstream_fleet_default_internet_access_disabled", "appstream_fleet_maximum_session_duration", "appstream_fleet_session_disconnect_timeout", @@ -3116,13 +2878,8 @@ "athena_workgroup_encryption", "athena_workgroup_enforce_configuration", "athena_workgroup_logging_enabled", - "autoscaling_group_capacity_rebalance_enabled", - "autoscaling_group_elb_health_check_enabled", "autoscaling_group_launch_configuration_no_public_ip", "autoscaling_group_launch_configuration_requires_imdsv2", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "autoscaling_group_using_ec2_launch_template", "awslambda_function_inside_vpc", "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", "awslambda_function_no_secrets_in_code", @@ -3131,19 +2888,14 @@ "awslambda_function_url_cors_policy", "awslambda_function_url_public", "awslambda_function_using_supported_runtimes", - "awslambda_function_vpc_multi_az", - "backup_plans_exist", "backup_recovery_point_encrypted", - "backup_reportplans_exist", "backup_vaults_encrypted", - "backup_vaults_exist", "bedrock_agent_guardrail_enabled", "bedrock_guardrail_prompt_attack_filter_enabled", "bedrock_guardrail_sensitive_information_filter_enabled", "bedrock_model_invocation_logging_enabled", "bedrock_model_invocation_logs_encryption_enabled", "cloudformation_stack_outputs_find_secrets", - "cloudformation_stacks_termination_protection_enabled", "cloudfront_distributions_custom_ssl_certificate", "cloudfront_distributions_default_root_object", "cloudfront_distributions_field_level_encryption_enabled", @@ -3151,10 +2903,8 @@ "cloudfront_distributions_https_enabled", "cloudfront_distributions_https_sni_enabled", "cloudfront_distributions_logging_enabled", - "cloudfront_distributions_multiple_origin_failover_configured", "cloudfront_distributions_origin_traffic_encrypted", "cloudfront_distributions_s3_origin_access_control", - "cloudfront_distributions_s3_origin_non_existent_bucket", "cloudfront_distributions_using_deprecated_ssl_protocols", "cloudfront_distributions_using_waf", "cloudtrail_bucket_requires_mfa_delete", @@ -3163,7 +2913,6 @@ "cloudtrail_kms_encryption_enabled", "cloudtrail_log_file_validation_enabled", "cloudtrail_logs_s3_bucket_access_logging_enabled", - "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", "cloudtrail_multi_region_enabled", "cloudtrail_multi_region_enabled_logging_management_events", "cloudtrail_s3_dataevents_read_enabled", @@ -3197,10 +2946,8 @@ "codeartifact_packages_external_public_publishing_disabled", "codebuild_project_logging_enabled", "codebuild_project_no_secrets_in_variables", - "codebuild_project_older_90_days", "codebuild_project_s3_logs_encrypted", "codebuild_project_source_repo_url_no_sensitive_credentials", - "codebuild_project_user_controlled_buildspec", "codebuild_report_group_export_encrypted", "cognito_identity_pool_guest_access_disabled", "cognito_user_pool_advanced_security_enabled", @@ -3221,37 +2968,24 @@ "config_recorder_all_regions_enabled", "config_recorder_using_aws_service_role", "datasync_task_logging_enabled", - "directconnect_connection_redundancy", - "directconnect_virtual_interface_redundancy", "directoryservice_directory_log_forwarding_enabled", "directoryservice_directory_monitor_notifications", - "directoryservice_directory_snapshots_limit", "directoryservice_ldap_certificate_expiration", "directoryservice_radius_server_security_protocol", "directoryservice_supported_mfa_radius_enabled", - "dlm_ebs_snapshot_lifecycle_policy_exists", "dms_endpoint_mongodb_authentication_enabled", "dms_endpoint_neptune_iam_authorization_enabled", "dms_endpoint_ssl_enabled", "dms_instance_minor_version_upgrade_enabled", - "dms_instance_multi_az_enabled", "dms_instance_no_public_access", - "documentdb_cluster_backup_enabled", "documentdb_cluster_cloudwatch_log_export", - "documentdb_cluster_deletion_protection", - "documentdb_cluster_multi_az_enabled", "documentdb_cluster_public_snapshot", "documentdb_cluster_storage_encrypted", "drs_job_exist", "dynamodb_accelerator_cluster_encryption_enabled", "dynamodb_accelerator_cluster_in_transit_encryption_enabled", - "dynamodb_accelerator_cluster_multi_az", - "dynamodb_table_autoscaling_enabled", "dynamodb_table_cross_account_access", - "dynamodb_table_deletion_protection_enabled", - "dynamodb_table_protected_by_backup_plan", "dynamodb_tables_kms_cmk_encryption_enabled", - "dynamodb_tables_pitr_enabled", "ec2_ami_public", "ec2_client_vpn_endpoint_connection_logging_enabled", "ec2_ebs_default_encryption", @@ -3259,17 +2993,11 @@ "ec2_ebs_snapshot_account_block_public_access", "ec2_ebs_snapshots_encrypted", "ec2_ebs_volume_encryption", - "ec2_ebs_volume_protected_by_backup_plan", - "ec2_ebs_volume_snapshots_exists", "ec2_elastic_ip_shodan", - "ec2_elastic_ip_unassigned", "ec2_instance_account_imdsv2_enabled", - "ec2_instance_detailed_monitoring_enabled", "ec2_instance_imdsv2_enabled", "ec2_instance_internet_facing_with_instance_profile", "ec2_instance_managed_by_ssm", - "ec2_instance_older_than_specific_days", - "ec2_instance_paravirtual_type", "ec2_instance_port_cassandra_exposed_to_internet", "ec2_instance_port_cifs_exposed_to_internet", "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", @@ -3321,17 +3049,12 @@ "ec2_securitygroup_with_many_ingress_egress_rules", "ec2_transitgateway_auto_accept_vpc_attachments", "ecr_registry_scan_images_on_push_enabled", - "ecr_repositories_lifecycle_policy_enabled", "ecr_repositories_not_publicly_accessible", "ecr_repositories_scan_vulnerabilities_in_latest_image", - "ecr_repositories_tag_immutability", - "ecs_cluster_container_insights_enabled", "ecs_service_fargate_latest_platform_version", "ecs_service_no_assign_public_ip", - "ecs_task_definitions_containers_readonly_access", "ecs_task_definitions_host_namespace_not_shared", "ecs_task_definitions_host_networking_mode_users", - "ecs_task_definitions_logging_block_mode", "ecs_task_definitions_logging_enabled", "ecs_task_definitions_no_environment_secrets", "ecs_task_definitions_no_privileged_containers", @@ -3339,7 +3062,6 @@ "efs_access_point_enforce_root_directory", "efs_access_point_enforce_user_identity", "efs_encryption_at_rest_enabled", - "efs_have_backup_enabled", "efs_mount_target_not_publicly_accessible", "efs_not_publicly_accessible", "eks_cluster_kms_cmk_encryption_in_secrets_enabled", @@ -3350,30 +3072,20 @@ "eks_control_plane_logging_all_types_enabled", "elasticache_cluster_uses_public_subnet", "elasticache_redis_cluster_auto_minor_version_upgrades", - "elasticache_redis_cluster_automatic_failover_enabled", - "elasticache_redis_cluster_backup_enabled", "elasticache_redis_cluster_in_transit_encryption_enabled", - "elasticache_redis_cluster_multi_az_enabled", "elasticache_redis_cluster_rest_encryption_enabled", "elasticache_redis_replication_group_auth_enabled", "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "elasticbeanstalk_environment_enhanced_health_reporting", "elasticbeanstalk_environment_managed_updates_enabled", - "elb_connection_draining_enabled", - "elb_cross_zone_load_balancing_enabled", "elb_desync_mitigation_mode", "elb_insecure_ssl_ciphers", "elb_internet_facing", - "elb_is_in_multiple_az", "elb_logging_enabled", "elb_ssl_listeners", "elb_ssl_listeners_use_acm_certificate", - "elbv2_cross_zone_load_balancing_enabled", - "elbv2_deletion_protection", "elbv2_desync_mitigation_mode", "elbv2_insecure_ssl_ciphers", "elbv2_internet_facing", - "elbv2_is_in_multiple_az", "elbv2_listeners_underneath", "elbv2_logging_enabled", "elbv2_nlb_tls_termination_enabled", @@ -3384,12 +3096,8 @@ "emr_cluster_publicly_accesible", "eventbridge_bus_cross_account_access", "eventbridge_bus_exposed", - "eventbridge_global_endpoint_event_replication_enabled", "eventbridge_schema_registry_cross_account_access", "fms_policy_compliant", - "fsx_file_system_copy_tags_to_backups_enabled", - "fsx_file_system_copy_tags_to_volumes_enabled", - "fsx_windows_file_system_multi_az_enabled", "glacier_vaults_policy_public_access", "glue_data_catalogs_connection_passwords_encryption_enabled", "glue_data_catalogs_metadata_encryption_enabled", @@ -3457,7 +3165,6 @@ "inspector2_active_findings_exist", "inspector2_is_enabled", "kafka_cluster_encryption_at_rest_uses_cmk", - "kafka_cluster_enhanced_monitoring_enabled", "kafka_cluster_in_transit_encryption_enabled", "kafka_cluster_is_public", "kafka_cluster_mutual_tls_authentication_enabled", @@ -3466,25 +3173,16 @@ "kafka_connector_in_transit_encryption_enabled", "kinesis_stream_encrypted_at_rest", "kms_cmk_are_used", - "kms_cmk_not_deleted_unintentionally", "kms_cmk_rotation_enabled", "kms_key_not_publicly_accessible", "lightsail_database_public", - "lightsail_instance_automated_snapshots", "lightsail_instance_public", - "lightsail_static_ip_unused", "macie_automated_sensitive_data_discovery_enabled", "macie_is_enabled", - "mq_broker_active_deployment_mode", "mq_broker_auto_minor_version_upgrades", - "mq_broker_cluster_deployment_mode", "mq_broker_logging_enabled", - "neptune_cluster_backup_enabled", - "neptune_cluster_copy_tags_to_snapshots", - "neptune_cluster_deletion_protection", "neptune_cluster_iam_authentication_enabled", "neptune_cluster_integration_cloudwatch_logs", - "neptune_cluster_multi_az", "neptune_cluster_public_snapshot", "neptune_cluster_snapshot_encrypted", "neptune_cluster_storage_encrypted", @@ -3492,15 +3190,12 @@ "networkfirewall_deletion_protection", "networkfirewall_in_all_vpc", "networkfirewall_logging_enabled", - "networkfirewall_multi_az", "networkfirewall_policy_default_action_fragmented_packets", "networkfirewall_policy_default_action_full_packets", "networkfirewall_policy_rule_group_associated", "opensearch_service_domains_audit_logging_enabled", "opensearch_service_domains_cloudwatch_logging_enabled", "opensearch_service_domains_encryption_at_rest_enabled", - "opensearch_service_domains_fault_tolerant_data_nodes", - "opensearch_service_domains_fault_tolerant_master_nodes", "opensearch_service_domains_https_communications_enforced", "opensearch_service_domains_internal_user_database_enabled", "opensearch_service_domains_node_to_node_encryption_enabled", @@ -3511,52 +3206,33 @@ "organizations_delegated_administrators", "organizations_opt_out_ai_services_policy", "organizations_scp_check_deny_regions", - "organizations_tags_policies_enabled_and_attached", - "rds_cluster_backtrack_enabled", - "rds_cluster_copy_tags_to_snapshots", "rds_cluster_critical_event_subscription", - "rds_cluster_default_admin", - "rds_cluster_deletion_protection", "rds_cluster_iam_authentication_enabled", "rds_cluster_integration_cloudwatch_logs", "rds_cluster_minor_version_upgrade_enabled", - "rds_cluster_multi_az", "rds_cluster_non_default_port", - "rds_cluster_protected_by_backup_plan", "rds_cluster_storage_encrypted", - "rds_instance_backup_enabled", "rds_instance_certificate_expiration", - "rds_instance_copy_tags_to_snapshots", "rds_instance_critical_event_subscription", - "rds_instance_default_admin", - "rds_instance_deletion_protection", "rds_instance_deprecated_engine_version", - "rds_instance_enhanced_monitoring_enabled", "rds_instance_event_subscription_parameter_groups", "rds_instance_event_subscription_security_groups", "rds_instance_iam_authentication_enabled", "rds_instance_inside_vpc", "rds_instance_integration_cloudwatch_logs", "rds_instance_minor_version_upgrade_enabled", - "rds_instance_multi_az", "rds_instance_no_public_access", "rds_instance_non_default_port", - "rds_instance_protected_by_backup_plan", "rds_instance_storage_encrypted", "rds_instance_transport_encrypted", "rds_snapshots_encrypted", "rds_snapshots_public_access", "redshift_cluster_audit_logging", - "redshift_cluster_automated_snapshot", "redshift_cluster_automatic_upgrades", "redshift_cluster_encrypted_at_rest", "redshift_cluster_enhanced_vpc_routing", "redshift_cluster_in_transit_encryption_enabled", - "redshift_cluster_multi_az_enabled", - "redshift_cluster_non_default_database_name", - "redshift_cluster_non_default_username", "redshift_cluster_public_access", - "resourceexplorer2_indexes_found", "route53_dangling_ip_subdomain_takeover", "route53_domains_privacy_protection_enabled", "route53_domains_transferlock_enabled", @@ -3565,15 +3241,11 @@ "s3_account_level_public_access_blocks", "s3_bucket_acl_prohibited", "s3_bucket_cross_account_access", - "s3_bucket_cross_region_replication", "s3_bucket_default_encryption", "s3_bucket_event_notifications_enabled", "s3_bucket_kms_encryption", "s3_bucket_level_public_access_block", - "s3_bucket_lifecycle_enabled", "s3_bucket_no_mfa_delete", - "s3_bucket_object_lock", - "s3_bucket_object_versioning", "s3_bucket_policy_public_write_access", "s3_bucket_public_access", "s3_bucket_public_list_acl", @@ -3581,7 +3253,6 @@ "s3_bucket_secure_transport_policy", "s3_bucket_server_access_logging_enabled", "s3_multi_region_access_point_public_access_block", - "sagemaker_endpoint_config_prod_variant_instances", "sagemaker_models_network_isolation_enabled", "sagemaker_models_vpc_settings_configured", "sagemaker_notebook_instance_encryption_enabled", @@ -3616,18 +3287,13 @@ "storagegateway_fileshare_encryption_enabled", "transfer_server_in_transit_encryption_enabled", "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", - "vpc_different_regions", "vpc_endpoint_connections_trust_boundaries", "vpc_endpoint_for_ec2_enabled", - "vpc_endpoint_multi_az_enabled", "vpc_endpoint_services_allowed_principals_trust_boundaries", "vpc_flow_logs_enabled", "vpc_peering_routing_tables_with_least_privilege", - "vpc_subnet_different_az", "vpc_subnet_no_public_ip_by_default", "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", "waf_global_rule_with_conditions", "waf_global_rulegroup_not_empty", "waf_global_webacl_logging_enabled", @@ -3648,10 +3314,10 @@ "Subdomain": "2.10 시스템 및 서비스 보안관리", "Section": "2.10.2 클라우드 보안", "AuditChecklist": [ - "클라우드 서비스 제공자와 정보보호 및 개인정보보호에 대한 책임과 역할을 명확히 정의하고 이를 계약서(SLA 등)에 반영하고 있는가?", - "클라우드 서비스 이용 시 서비스 유형에 따른 보안위험을 평가하여 비인가 접근, 설정오류 등을 방지할 수 있도록 보안 구성 및 설정 기준, 보안설정 변경 및 승인 절차, 안전한 접속방법, 권한 체계 등 보안 통제 정책을 수립·이행하고 있는가?", - "클라우드 서비스 관리자 권한은 역할에 따라 최소화하여 부여하고 관리자 권한에 대한 비인가 접근, 권한 오·남용 등을 방지할 수 있도록 강화된 인증, 암호화, 접근통제, 감사기록 등 보호대책을 적용하고 있는가?", - "클라우드 서비스의 보안 설정 변경, 운영 현황 등을 모니터링하고 그 적절성을 정기적으로 검토하고 있는가?" + "클라우드 서비스 제공자와 정보보호 및 개인정보보호에 대한 책임과 역할을 명확히 정의하고 이를 계약서(SLA 등)에 반영하고 있는가?", + "클라우드 서비스 이용 시 서비스 유형에 따른 보안위험을 평가하여 비인가 접근, 설정오류 등을 방지할 수 있도록 보안 구성 및 설정 기준, 보안설정 변경 및 승인 절차, 안전한 접속방법, 권한 체계 등 보안 통제 정책을 수립·이행하고 있는가?", + "클라우드 서비스 관리자 권한은 역할에 따라 최소화하여 부여하고 관리자 권한에 대한 비인가 접근, 권한 오·남용 등을 방지할 수 있도록 강화된 인증, 암호화, 접근통제, 감사기록 등 보호대책을 적용하고 있는가?", + "클라우드 서비스의 보안 설정 변경, 운영 현황 등을 모니터링하고 그 적절성을 정기적으로 검토하고 있는가?" ], "RelatedRegulations": [], "AuditEvidence": [ @@ -3676,41 +3342,7 @@ "Id": "2.10.3", "Name": "공개서버 보안", "Description": "외부 네트워크에 공개되는 서버의 경우 내부 네트워크와 분리하고 취약점 점검, 접근통제, 인증, 정보 수집·저장·공개 절차 등 강화된 보호대책을 수립·이행하여야 한다.", - "Checks": [ - "acm_certificates_expiration_check", - "acm_certificates_transparency_logs_enabled", - "acm_certificates_with_secure_key_algorithms", - "apigateway_restapi_client_certificate_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", - "apigateway_restapi_waf_acl_attached", - "cloudfront_distributions_s3_origin_non_existent_bucket", - "cloudfront_distributions_using_waf", - "cognito_user_pool_waf_acl_attached", - "elb_desync_mitigation_mode", - "elb_insecure_ssl_ciphers", - "elb_internet_facing", - "elb_ssl_listeners", - "elb_ssl_listeners_use_acm_certificate", - "elbv2_desync_mitigation_mode", - "elbv2_insecure_ssl_ciphers", - "elbv2_internet_facing", - "elbv2_listeners_underneath", - "elbv2_nlb_tls_termination_enabled", - "elbv2_ssl_listeners", - "elbv2_waf_acl_attached", - "lightsail_database_public", - "lightsail_instance_public", - "lightsail_static_ip_unused", - "route53_dangling_ip_subdomain_takeover", - "route53_domains_privacy_protection_enabled", - "shield_advanced_protection_in_associated_elastic_ips", - "shield_advanced_protection_in_classic_load_balancers", - "shield_advanced_protection_in_cloudfront_distributions", - "shield_advanced_protection_in_global_accelerators", - "shield_advanced_protection_in_internet_facing_load_balancers", - "shield_advanced_protection_in_route53_hosted_zones" - ], + "Checks": [], "Attributes": [ { "Domain": "2. 보호대책 요구사항", @@ -3747,7 +3379,7 @@ "Subdomain": "2.10 시스템 및 서비스 보안관리", "Section": "2.10.4 전자거래 및 핀테크 보안", "AuditChecklist": [ - "전자거래 및 핀테크 서비스를 제공하는 경우 거래의 안전성과 신뢰성 확보를 위한 보호대책을 수립·이행하고 있는가?", + "전자거래 및 핀테크 서비스를 제공하는 경우 거래의 안전성과 신뢰성 확보를 위한 보호대책을 수립·이행하고 있는가?", "전자거래 및 핀테크 서비스 제공을 위하여 결제시스템 등 외부 시스템과 연계하는 경우 송수신되는 관련 정보의 보호를 위한 대책을 수립·이행하고 안전성을 점검하고 있는가?" ], "RelatedRegulations": [], @@ -3756,8 +3388,8 @@ "결제시스템 연계 시 보안성 검토 결과" ], "NonComplianceCases": [ - "사례 1 : 전자결제대행업체와 위탁 계약을 맺고 연계를 하였으나, 적절한 인증 및 접근제한 없이 특정 URL을 통하여 결제 관련 정보가 모두 평문으로 전송되는 경우,", - "사례 2 : 전자결제대행업체와 외부 연계 시스템이 전용망으로 연결되어 있으나, 해당 연계 시스템에서 내부 업무 시스템으로의 접근이 침입차단시스템 등으로 적절히 통제되지 않고 있는 경우,", + "사례 1 : 전자결제대행업체와 위탁 계약을 맺고 연계를 하였으나, 적절한 인증 및 접근제한 없이 특정 URL을 통하여 결제 관련 정보가 모두 평문으로 전송되는 경우", + "사례 2 : 전자결제대행업체와 외부 연계 시스템이 전용망으로 연결되어 있으나, 해당 연계 시스템에서 내부 업무 시스템으로의 접근이 침입차단시스템 등으로 적절히 통제되지 않고 있는 경우", "사례 3 : 내부 지침에는 외부 핀테크 서비스 연계 시 정보보호팀의 보안성 검토를 받도록 되어 있으나, 최근에 신규 핀테크 서비스를 연계하면서 일정상 이유로 보안성 검토를 수행하지 않은 경우" ] } @@ -3802,7 +3434,7 @@ "Section": "2.10.6 업무용 단말기기 보안", "AuditChecklist": [ "PC, 노트북, 가상PC, 태블릿 등 업무에 사용되는 단말기에 대하여 기기인증, 승인, 접근범위 설정, 기기 보안설정 등의 보안 통제 정책을 수립·이행하고 있는가?", - "업무용 단말기를 통하여 개인정보 및 중요정보가 유출되는 것을 방지하기 위하여 자료공유프로그램 사용 금지, 공유설정 제한, 무선망 이용 통제 등의 정책을 수립 및 이행하고 있는가?", + "업무용 단말기를 통하여 개인정보 및 중요정보가 유출되는 것을 방지하기 위하여 자료공유프로그램 사용 금지, 공유설정 제한, 무선망 이용 통제 등의 정책을 수립·이행하고 있는가?", "업무용 모바일 기기의 분실, 도난 등으로 인한 개인정보 및 중요정보의 유·노출을 방지하기 위하여 보안대책을 적용하고 있는가?", "업무용 단말기기에 대한 접근통제 대책의 적절성에 대하여 주기적으로 점검하고 있는가?" ], @@ -3913,7 +3545,7 @@ { "Id": "2.10.9", "Name": "악성코드 통제", - "Description": "바이러스·웜·트로이목마·랜섬웨어 등의 악성코드로부터 개인정보 및 중요정보, 정보시스템 및 업무용 단말기 등을 보호하기 위하여 악성코드 예방·탐지·대응 등의 보호대책을 수립 및 이행하여야 한다.", + "Description": "바이러스·웜·트로이목마·랜섬웨어 등의 악성코드로부터 개인정보 및 중요정보, 정보시스템 및 업무용 단말기 등을 보호하기 위하여 악성코드 예방·탐지·대응 등의 보호대책을 수립·이행하여야 한다.", "Checks": [ "guardduty_ec2_malware_protection_enabled" ], @@ -3926,7 +3558,7 @@ "바이러스, 웜, 트로이목마, 랜섬웨어 등의 악성코드로부터 정보시스템 및 업무용단말기 등을 보호하기 위하여 보호대책을 수립·이행하고 있는가?", "백신 소프트웨어 등 보안프로그램을 통하여 최신 악성코드 예방·탐지 활동을 지속적으로 수행하고 있는가?", "백신 소프트웨어 등 보안프로그램은 최신의 상태로 유지하고 필요시 긴급 보안 업데이트를 수행하고 있는가?", - "악성코드 감염 발견 시 악성코드 확산 및 피해 최소화 등의 대응절차를 수립·이행하고 있는가?" + "악성코드 감염 발견 시 악성코드 확산 및 피해 최소화 등의 대응절차를 수립·이행하고 있는가?" ], "RelatedRegulations": [ "개인정보 보호법 제29조(안전조치의무)", @@ -3952,12 +3584,6 @@ "Name": "사고 예방 및 대응체계 구축", "Description": "침해사고 및 개인정보 유출 등을 예방하고 사고 발생 시 신속하고 효과적으로 대응할 수 있도록 내·외부 침해시도의 탐지·대응·분석 및 공유를 위한 체계와 절차를 수립하고, 관련 외부기관 및 전문가들과 협조체계를 구축하여야 한다.", "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", - "account_security_questions_are_registered_in_the_aws_account", - "acm_certificates_with_secure_key_algorithms", - "guardduty_centrally_managed", "iam_support_role_created", "ssmincidents_enabled_with_plans" ], @@ -3996,557 +3622,9 @@ "Name": "취약점 점검 및 조치", "Description": "정보시스템의 취약점이 노출되어 있는지를 확인하기 위하여 정기적으로 취약점 점검을 수행하고, 발견된 취약점에 대해서는 신속하게 조치하여야 한다. 또한 최신 보안취약점의 발생 여부를 지속적으로 파악하고, 정보시스템에 미치는 영향을 분석하여 조치하여야 한다.", "Checks": [ - "accessanalyzer_enabled", - "accessanalyzer_enabled_without_findings", - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", - "account_security_questions_are_registered_in_the_aws_account", - "acm_certificates_expiration_check", - "acm_certificates_transparency_logs_enabled", - "acm_certificates_with_secure_key_algorithms", - "apigateway_restapi_authorizers_enabled", - "apigateway_restapi_cache_encrypted", - "apigateway_restapi_client_certificate_enabled", - "apigateway_restapi_logging_enabled", - "apigateway_restapi_public", - "apigateway_restapi_public_with_authorizer", - "apigateway_restapi_tracing_enabled", - "apigateway_restapi_waf_acl_attached", - "apigatewayv2_api_access_logging_enabled", - "apigatewayv2_api_authorizers_enabled", - "appstream_fleet_default_internet_access_disabled", - "appstream_fleet_maximum_session_duration", - "appstream_fleet_session_disconnect_timeout", - "appstream_fleet_session_idle_disconnect_timeout", - "athena_workgroup_encryption", - "athena_workgroup_enforce_configuration", - "athena_workgroup_logging_enabled", - "autoscaling_group_capacity_rebalance_enabled", - "autoscaling_group_elb_health_check_enabled", - "autoscaling_group_launch_configuration_no_public_ip", - "autoscaling_group_launch_configuration_requires_imdsv2", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "autoscaling_group_using_ec2_launch_template", - "awslambda_function_inside_vpc", - "awslambda_function_invoke_api_operations_cloudtrail_logging_enabled", - "awslambda_function_no_secrets_in_code", - "awslambda_function_no_secrets_in_variables", - "awslambda_function_not_publicly_accessible", - "awslambda_function_url_cors_policy", - "awslambda_function_url_public", - "awslambda_function_using_supported_runtimes", - "awslambda_function_vpc_multi_az", - "backup_plans_exist", - "backup_recovery_point_encrypted", - "backup_reportplans_exist", - "backup_vaults_encrypted", - "backup_vaults_exist", - "bedrock_agent_guardrail_enabled", - "bedrock_guardrail_prompt_attack_filter_enabled", - "bedrock_guardrail_sensitive_information_filter_enabled", - "bedrock_model_invocation_logging_enabled", - "bedrock_model_invocation_logs_encryption_enabled", - "cloudformation_stack_outputs_find_secrets", - "cloudformation_stacks_termination_protection_enabled", - "cloudfront_distributions_custom_ssl_certificate", - "cloudfront_distributions_default_root_object", - "cloudfront_distributions_field_level_encryption_enabled", - "cloudfront_distributions_geo_restrictions_enabled", - "cloudfront_distributions_https_enabled", - "cloudfront_distributions_https_sni_enabled", - "cloudfront_distributions_logging_enabled", - "cloudfront_distributions_multiple_origin_failover_configured", - "cloudfront_distributions_origin_traffic_encrypted", - "cloudfront_distributions_s3_origin_access_control", - "cloudfront_distributions_s3_origin_non_existent_bucket", - "cloudfront_distributions_using_deprecated_ssl_protocols", - "cloudfront_distributions_using_waf", - "cloudtrail_bucket_requires_mfa_delete", - "cloudtrail_cloudwatch_logging_enabled", - "cloudtrail_insights_exist", - "cloudtrail_kms_encryption_enabled", - "cloudtrail_log_file_validation_enabled", - "cloudtrail_logs_s3_bucket_access_logging_enabled", - "cloudtrail_logs_s3_bucket_is_not_publicly_accessible", - "cloudtrail_multi_region_enabled", - "cloudtrail_multi_region_enabled_logging_management_events", - "cloudtrail_s3_dataevents_read_enabled", - "cloudtrail_s3_dataevents_write_enabled", - "cloudtrail_threat_detection_enumeration", - "cloudtrail_threat_detection_llm_jacking", - "cloudtrail_threat_detection_privilege_escalation", - "cloudwatch_alarm_actions_alarm_state_configured", - "cloudwatch_alarm_actions_enabled", - "cloudwatch_changes_to_network_acls_alarm_configured", - "cloudwatch_changes_to_network_gateways_alarm_configured", - "cloudwatch_changes_to_network_route_tables_alarm_configured", - "cloudwatch_changes_to_vpcs_alarm_configured", - "cloudwatch_cross_account_sharing_disabled", - "cloudwatch_log_group_kms_encryption_enabled", - "cloudwatch_log_group_no_critical_pii_in_logs", - "cloudwatch_log_group_no_secrets_in_logs", - "cloudwatch_log_group_not_publicly_accessible", - "cloudwatch_log_group_retention_policy_specific_days_enabled", - "cloudwatch_log_metric_filter_and_alarm_for_aws_config_configuration_changes_enabled", - "cloudwatch_log_metric_filter_and_alarm_for_cloudtrail_configuration_changes_enabled", - "cloudwatch_log_metric_filter_authentication_failures", - "cloudwatch_log_metric_filter_aws_organizations_changes", - "cloudwatch_log_metric_filter_disable_or_scheduled_deletion_of_kms_cmk", - "cloudwatch_log_metric_filter_for_s3_bucket_policy_changes", - "cloudwatch_log_metric_filter_policy_changes", - "cloudwatch_log_metric_filter_root_usage", - "cloudwatch_log_metric_filter_security_group_changes", - "cloudwatch_log_metric_filter_sign_in_without_mfa", - "cloudwatch_log_metric_filter_unauthorized_api_calls", - "codeartifact_packages_external_public_publishing_disabled", - "codebuild_project_logging_enabled", - "codebuild_project_no_secrets_in_variables", - "codebuild_project_older_90_days", - "codebuild_project_s3_logs_encrypted", - "codebuild_project_source_repo_url_no_sensitive_credentials", - "codebuild_project_user_controlled_buildspec", - "codebuild_report_group_export_encrypted", - "cognito_identity_pool_guest_access_disabled", - "cognito_user_pool_advanced_security_enabled", - "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", - "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", - "cognito_user_pool_client_prevent_user_existence_errors", - "cognito_user_pool_client_token_revocation_enabled", - "cognito_user_pool_deletion_protection_enabled", - "cognito_user_pool_mfa_enabled", - "cognito_user_pool_password_policy_lowercase", - "cognito_user_pool_password_policy_minimum_length_14", - "cognito_user_pool_password_policy_number", - "cognito_user_pool_password_policy_symbol", - "cognito_user_pool_password_policy_uppercase", - "cognito_user_pool_self_registration_disabled", - "cognito_user_pool_temporary_password_expiration", - "cognito_user_pool_waf_acl_attached", - "config_recorder_all_regions_enabled", - "config_recorder_using_aws_service_role", - "datasync_task_logging_enabled", - "directconnect_connection_redundancy", - "directconnect_virtual_interface_redundancy", - "directoryservice_directory_log_forwarding_enabled", - "directoryservice_directory_monitor_notifications", - "directoryservice_directory_snapshots_limit", - "directoryservice_ldap_certificate_expiration", - "directoryservice_radius_server_security_protocol", - "directoryservice_supported_mfa_radius_enabled", - "dlm_ebs_snapshot_lifecycle_policy_exists", - "dms_endpoint_mongodb_authentication_enabled", - "dms_endpoint_neptune_iam_authorization_enabled", - "dms_endpoint_ssl_enabled", - "dms_instance_minor_version_upgrade_enabled", - "dms_instance_multi_az_enabled", - "dms_instance_no_public_access", - "documentdb_cluster_backup_enabled", - "documentdb_cluster_cloudwatch_log_export", - "documentdb_cluster_deletion_protection", - "documentdb_cluster_multi_az_enabled", - "documentdb_cluster_public_snapshot", - "documentdb_cluster_storage_encrypted", - "drs_job_exist", - "dynamodb_accelerator_cluster_encryption_enabled", - "dynamodb_accelerator_cluster_in_transit_encryption_enabled", - "dynamodb_accelerator_cluster_multi_az", - "dynamodb_table_autoscaling_enabled", - "dynamodb_table_cross_account_access", - "dynamodb_table_deletion_protection_enabled", - "dynamodb_table_protected_by_backup_plan", - "dynamodb_tables_kms_cmk_encryption_enabled", - "dynamodb_tables_pitr_enabled", - "ec2_ami_public", - "ec2_client_vpn_endpoint_connection_logging_enabled", - "ec2_ebs_default_encryption", - "ec2_ebs_public_snapshot", - "ec2_ebs_snapshot_account_block_public_access", - "ec2_ebs_snapshots_encrypted", - "ec2_ebs_volume_encryption", - "ec2_ebs_volume_protected_by_backup_plan", - "ec2_ebs_volume_snapshots_exists", - "ec2_elastic_ip_shodan", - "ec2_elastic_ip_unassigned", - "ec2_instance_account_imdsv2_enabled", - "ec2_instance_detailed_monitoring_enabled", - "ec2_instance_imdsv2_enabled", - "ec2_instance_internet_facing_with_instance_profile", - "ec2_instance_managed_by_ssm", - "ec2_instance_older_than_specific_days", - "ec2_instance_paravirtual_type", - "ec2_instance_port_cassandra_exposed_to_internet", - "ec2_instance_port_cifs_exposed_to_internet", - "ec2_instance_port_elasticsearch_kibana_exposed_to_internet", - "ec2_instance_port_ftp_exposed_to_internet", - "ec2_instance_port_kafka_exposed_to_internet", - "ec2_instance_port_kerberos_exposed_to_internet", - "ec2_instance_port_ldap_exposed_to_internet", - "ec2_instance_port_memcached_exposed_to_internet", - "ec2_instance_port_mongodb_exposed_to_internet", - "ec2_instance_port_mysql_exposed_to_internet", - "ec2_instance_port_oracle_exposed_to_internet", - "ec2_instance_port_postgresql_exposed_to_internet", - "ec2_instance_port_rdp_exposed_to_internet", - "ec2_instance_port_redis_exposed_to_internet", - "ec2_instance_port_sqlserver_exposed_to_internet", - "ec2_instance_port_ssh_exposed_to_internet", - "ec2_instance_port_telnet_exposed_to_internet", - "ec2_instance_profile_attached", - "ec2_instance_public_ip", - "ec2_instance_secrets_user_data", - "ec2_instance_uses_single_eni", - "ec2_launch_template_no_public_ip", - "ec2_launch_template_no_secrets", - "ec2_networkacl_allow_ingress_any_port", - "ec2_networkacl_allow_ingress_tcp_port_22", - "ec2_networkacl_allow_ingress_tcp_port_3389", - "ec2_networkacl_unused", - "ec2_securitygroup_allow_ingress_from_internet_to_all_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_any_port", - "ec2_securitygroup_allow_ingress_from_internet_to_high_risk_tcp_ports", - "ec2_securitygroup_allow_ingress_from_internet_to_port_mongodb_27017_27018", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_ftp_port_20_21", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_22", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_3389", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_cassandra_7199_9160_8888", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_elasticsearch_kibana_9200_9300_5601", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_kafka_9092", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_memcached_11211", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_mysql_3306", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_oracle_1521_2483", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_postgres_5432", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_redis_6379", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_sql_server_1433_1434", - "ec2_securitygroup_allow_ingress_from_internet_to_tcp_port_telnet_23", - "ec2_securitygroup_allow_wide_open_public_ipv4", - "ec2_securitygroup_default_restrict_traffic", - "ec2_securitygroup_from_launch_wizard", - "ec2_securitygroup_not_used", - "ec2_securitygroup_with_many_ingress_egress_rules", - "ec2_transitgateway_auto_accept_vpc_attachments", "ecr_registry_scan_images_on_push_enabled", - "ecr_repositories_lifecycle_policy_enabled", - "ecr_repositories_not_publicly_accessible", "ecr_repositories_scan_vulnerabilities_in_latest_image", - "ecr_repositories_tag_immutability", - "ecs_cluster_container_insights_enabled", - "ecs_service_fargate_latest_platform_version", - "ecs_service_no_assign_public_ip", - "ecs_task_definitions_containers_readonly_access", - "ecs_task_definitions_host_namespace_not_shared", - "ecs_task_definitions_host_networking_mode_users", - "ecs_task_definitions_logging_block_mode", - "ecs_task_definitions_logging_enabled", - "ecs_task_definitions_no_environment_secrets", - "ecs_task_definitions_no_privileged_containers", - "ecs_task_set_no_assign_public_ip", - "efs_access_point_enforce_root_directory", - "efs_access_point_enforce_user_identity", - "efs_encryption_at_rest_enabled", - "efs_have_backup_enabled", - "efs_mount_target_not_publicly_accessible", - "efs_not_publicly_accessible", - "eks_cluster_kms_cmk_encryption_in_secrets_enabled", - "eks_cluster_network_policy_enabled", - "eks_cluster_not_publicly_accessible", - "eks_cluster_private_nodes_enabled", - "eks_cluster_uses_a_supported_version", - "eks_control_plane_logging_all_types_enabled", - "elasticache_cluster_uses_public_subnet", - "elasticache_redis_cluster_auto_minor_version_upgrades", - "elasticache_redis_cluster_automatic_failover_enabled", - "elasticache_redis_cluster_backup_enabled", - "elasticache_redis_cluster_in_transit_encryption_enabled", - "elasticache_redis_cluster_multi_az_enabled", - "elasticache_redis_cluster_rest_encryption_enabled", - "elasticache_redis_replication_group_auth_enabled", - "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "elasticbeanstalk_environment_enhanced_health_reporting", - "elasticbeanstalk_environment_managed_updates_enabled", - "elb_connection_draining_enabled", - "elb_cross_zone_load_balancing_enabled", - "elb_desync_mitigation_mode", - "elb_insecure_ssl_ciphers", - "elb_internet_facing", - "elb_is_in_multiple_az", - "elb_logging_enabled", - "elb_ssl_listeners", - "elb_ssl_listeners_use_acm_certificate", - "elbv2_cross_zone_load_balancing_enabled", - "elbv2_deletion_protection", - "elbv2_desync_mitigation_mode", - "elbv2_insecure_ssl_ciphers", - "elbv2_internet_facing", - "elbv2_is_in_multiple_az", - "elbv2_listeners_underneath", - "elbv2_logging_enabled", - "elbv2_nlb_tls_termination_enabled", - "elbv2_ssl_listeners", - "elbv2_waf_acl_attached", - "emr_cluster_account_public_block_enabled", - "emr_cluster_master_nodes_no_public_ip", - "emr_cluster_publicly_accesible", - "eventbridge_bus_cross_account_access", - "eventbridge_bus_exposed", - "eventbridge_global_endpoint_event_replication_enabled", - "eventbridge_schema_registry_cross_account_access", - "fms_policy_compliant", - "fsx_file_system_copy_tags_to_backups_enabled", - "fsx_file_system_copy_tags_to_volumes_enabled", - "fsx_windows_file_system_multi_az_enabled", - "glacier_vaults_policy_public_access", - "glue_data_catalogs_connection_passwords_encryption_enabled", - "glue_data_catalogs_metadata_encryption_enabled", - "glue_data_catalogs_not_publicly_accessible", - "glue_database_connections_ssl_enabled", - "glue_development_endpoints_cloudwatch_logs_encryption_enabled", - "glue_development_endpoints_job_bookmark_encryption_enabled", - "glue_development_endpoints_s3_encryption_enabled", - "glue_etl_jobs_amazon_s3_encryption_enabled", - "glue_etl_jobs_cloudwatch_logs_encryption_enabled", - "glue_etl_jobs_job_bookmark_encryption_enabled", - "glue_etl_jobs_logging_enabled", - "glue_ml_transform_encrypted_at_rest", - "guardduty_centrally_managed", - "guardduty_ec2_malware_protection_enabled", - "guardduty_eks_audit_log_enabled", - "guardduty_eks_runtime_monitoring_enabled", - "guardduty_is_enabled", - "guardduty_lambda_protection_enabled", - "guardduty_no_high_severity_findings", - "guardduty_rds_protection_enabled", - "guardduty_s3_protection_enabled", - "iam_administrator_access_with_mfa", - "iam_avoid_root_usage", - "iam_aws_attached_policy_no_administrative_privileges", - "iam_check_saml_providers_sts", - "iam_customer_attached_policy_no_administrative_privileges", - "iam_customer_unattached_policy_no_administrative_privileges", - "iam_group_administrator_access_policy", - "iam_inline_policy_allows_privilege_escalation", - "iam_inline_policy_no_administrative_privileges", - "iam_inline_policy_no_full_access_to_cloudtrail", - "iam_inline_policy_no_full_access_to_kms", - "iam_no_custom_policy_permissive_role_assumption", - "iam_no_expired_server_certificates_stored", - "iam_no_root_access_key", - "iam_password_policy_expires_passwords_within_90_days_or_less", - "iam_password_policy_lowercase", - "iam_password_policy_minimum_length_14", - "iam_password_policy_number", - "iam_password_policy_reuse_24", - "iam_password_policy_symbol", - "iam_password_policy_uppercase", - "iam_policy_allows_privilege_escalation", - "iam_policy_attached_only_to_group_or_roles", - "iam_policy_cloudshell_admin_not_attached", - "iam_policy_no_full_access_to_cloudtrail", - "iam_policy_no_full_access_to_kms", - "iam_role_administratoraccess_policy", - "iam_role_cross_account_readonlyaccess_policy", - "iam_role_cross_service_confused_deputy_prevention", - "iam_root_hardware_mfa_enabled", - "iam_root_mfa_enabled", - "iam_rotate_access_key_90_days", - "iam_securityaudit_role_created", - "iam_support_role_created", - "iam_user_accesskey_unused", - "iam_user_administrator_access_policy", - "iam_user_console_access_unused", - "iam_user_hardware_mfa_enabled", - "iam_user_mfa_enabled_console_access", - "iam_user_no_setup_initial_access_key", - "iam_user_two_active_access_key", - "iam_user_with_temporary_credentials", - "inspector2_active_findings_exist", - "inspector2_is_enabled", - "kafka_cluster_encryption_at_rest_uses_cmk", - "kafka_cluster_enhanced_monitoring_enabled", - "kafka_cluster_in_transit_encryption_enabled", - "kafka_cluster_is_public", - "kafka_cluster_mutual_tls_authentication_enabled", - "kafka_cluster_unrestricted_access_disabled", - "kafka_cluster_uses_latest_version", - "kafka_connector_in_transit_encryption_enabled", - "kinesis_stream_encrypted_at_rest", - "kms_cmk_are_used", - "kms_cmk_not_deleted_unintentionally", - "kms_cmk_rotation_enabled", - "kms_key_not_publicly_accessible", - "lightsail_database_public", - "lightsail_instance_automated_snapshots", - "lightsail_instance_public", - "lightsail_static_ip_unused", - "macie_automated_sensitive_data_discovery_enabled", - "macie_is_enabled", - "mq_broker_active_deployment_mode", - "mq_broker_auto_minor_version_upgrades", - "mq_broker_cluster_deployment_mode", - "mq_broker_logging_enabled", - "neptune_cluster_backup_enabled", - "neptune_cluster_copy_tags_to_snapshots", - "neptune_cluster_deletion_protection", - "neptune_cluster_iam_authentication_enabled", - "neptune_cluster_integration_cloudwatch_logs", - "neptune_cluster_multi_az", - "neptune_cluster_public_snapshot", - "neptune_cluster_snapshot_encrypted", - "neptune_cluster_storage_encrypted", - "neptune_cluster_uses_public_subnet", - "networkfirewall_deletion_protection", - "networkfirewall_in_all_vpc", - "networkfirewall_logging_enabled", - "networkfirewall_multi_az", - "networkfirewall_policy_default_action_fragmented_packets", - "networkfirewall_policy_default_action_full_packets", - "networkfirewall_policy_rule_group_associated", - "opensearch_service_domains_audit_logging_enabled", - "opensearch_service_domains_cloudwatch_logging_enabled", - "opensearch_service_domains_encryption_at_rest_enabled", - "opensearch_service_domains_fault_tolerant_data_nodes", - "opensearch_service_domains_fault_tolerant_master_nodes", - "opensearch_service_domains_https_communications_enforced", - "opensearch_service_domains_internal_user_database_enabled", - "opensearch_service_domains_node_to_node_encryption_enabled", - "opensearch_service_domains_not_publicly_accessible", - "opensearch_service_domains_updated_to_the_latest_service_software_version", - "opensearch_service_domains_use_cognito_authentication_for_kibana", - "organizations_account_part_of_organizations", - "organizations_delegated_administrators", - "organizations_opt_out_ai_services_policy", - "organizations_scp_check_deny_regions", - "organizations_tags_policies_enabled_and_attached", - "rds_cluster_backtrack_enabled", - "rds_cluster_copy_tags_to_snapshots", - "rds_cluster_critical_event_subscription", - "rds_cluster_default_admin", - "rds_cluster_deletion_protection", - "rds_cluster_iam_authentication_enabled", - "rds_cluster_integration_cloudwatch_logs", - "rds_cluster_minor_version_upgrade_enabled", - "rds_cluster_multi_az", - "rds_cluster_non_default_port", - "rds_cluster_protected_by_backup_plan", - "rds_cluster_storage_encrypted", - "rds_instance_backup_enabled", - "rds_instance_certificate_expiration", - "rds_instance_copy_tags_to_snapshots", - "rds_instance_critical_event_subscription", - "rds_instance_default_admin", - "rds_instance_deletion_protection", - "rds_instance_deprecated_engine_version", - "rds_instance_enhanced_monitoring_enabled", - "rds_instance_event_subscription_parameter_groups", - "rds_instance_event_subscription_security_groups", - "rds_instance_iam_authentication_enabled", - "rds_instance_inside_vpc", - "rds_instance_integration_cloudwatch_logs", - "rds_instance_minor_version_upgrade_enabled", - "rds_instance_multi_az", - "rds_instance_no_public_access", - "rds_instance_non_default_port", - "rds_instance_protected_by_backup_plan", - "rds_instance_storage_encrypted", - "rds_instance_transport_encrypted", - "rds_snapshots_encrypted", - "rds_snapshots_public_access", - "redshift_cluster_audit_logging", - "redshift_cluster_automated_snapshot", - "redshift_cluster_automatic_upgrades", - "redshift_cluster_encrypted_at_rest", - "redshift_cluster_enhanced_vpc_routing", - "redshift_cluster_in_transit_encryption_enabled", - "redshift_cluster_multi_az_enabled", - "redshift_cluster_non_default_database_name", - "redshift_cluster_non_default_username", - "redshift_cluster_public_access", - "resourceexplorer2_indexes_found", - "route53_dangling_ip_subdomain_takeover", - "route53_domains_privacy_protection_enabled", - "route53_domains_transferlock_enabled", - "route53_public_hosted_zones_cloudwatch_logging_enabled", - "s3_access_point_public_access_block", - "s3_account_level_public_access_blocks", - "s3_bucket_acl_prohibited", - "s3_bucket_cross_account_access", - "s3_bucket_cross_region_replication", - "s3_bucket_default_encryption", - "s3_bucket_event_notifications_enabled", - "s3_bucket_kms_encryption", - "s3_bucket_level_public_access_block", - "s3_bucket_lifecycle_enabled", - "s3_bucket_no_mfa_delete", - "s3_bucket_object_lock", - "s3_bucket_object_versioning", - "s3_bucket_policy_public_write_access", - "s3_bucket_public_access", - "s3_bucket_public_list_acl", - "s3_bucket_public_write_acl", - "s3_bucket_secure_transport_policy", - "s3_bucket_server_access_logging_enabled", - "s3_multi_region_access_point_public_access_block", - "sagemaker_endpoint_config_prod_variant_instances", - "sagemaker_models_network_isolation_enabled", - "sagemaker_models_vpc_settings_configured", - "sagemaker_notebook_instance_encryption_enabled", - "sagemaker_notebook_instance_root_access_disabled", - "sagemaker_notebook_instance_vpc_settings_configured", - "sagemaker_notebook_instance_without_direct_internet_access_configured", - "sagemaker_training_jobs_intercontainer_encryption_enabled", - "sagemaker_training_jobs_network_isolation_enabled", - "sagemaker_training_jobs_volume_and_output_encryption_enabled", - "sagemaker_training_jobs_vpc_settings_configured", - "secretsmanager_automatic_rotation_enabled", - "secretsmanager_not_publicly_accessible", - "secretsmanager_secret_rotated_periodically", - "secretsmanager_secret_unused", - "securityhub_enabled", - "ses_identity_not_publicly_accessible", - "shield_advanced_protection_in_associated_elastic_ips", - "shield_advanced_protection_in_classic_load_balancers", - "shield_advanced_protection_in_cloudfront_distributions", - "shield_advanced_protection_in_global_accelerators", - "shield_advanced_protection_in_internet_facing_load_balancers", - "shield_advanced_protection_in_route53_hosted_zones", - "sns_subscription_not_using_http_endpoints", - "sns_topics_kms_encryption_at_rest_enabled", - "sns_topics_not_publicly_accessible", - "sqs_queues_not_publicly_accessible", - "sqs_queues_server_side_encryption_enabled", - "ssm_document_secrets", - "ssm_documents_set_as_public", - "ssm_managed_compliant_patching", - "ssmincidents_enabled_with_plans", - "storagegateway_fileshare_encryption_enabled", - "transfer_server_in_transit_encryption_enabled", - "trustedadvisor_errors_and_warnings", - "trustedadvisor_premium_support_plan_subscribed", - "vpc_different_regions", - "vpc_endpoint_connections_trust_boundaries", - "vpc_endpoint_for_ec2_enabled", - "vpc_endpoint_multi_az_enabled", - "vpc_endpoint_services_allowed_principals_trust_boundaries", - "vpc_flow_logs_enabled", - "vpc_peering_routing_tables_with_least_privilege", - "vpc_subnet_different_az", - "vpc_subnet_no_public_ip_by_default", - "vpc_subnet_separate_private_public", - "vpc_vpn_connection_tunnels_up", - "waf_global_rule_with_conditions", - "waf_global_rulegroup_not_empty", - "waf_global_webacl_logging_enabled", - "waf_global_webacl_with_rules", - "waf_regional_rule_with_conditions", - "waf_regional_rulegroup_not_empty", - "waf_regional_webacl_with_rules", - "wafv2_webacl_logging_enabled", - "wafv2_webacl_rule_logging_enabled", - "wafv2_webacl_with_rules", - "wellarchitected_workload_no_high_or_medium_risks", - "workspaces_volume_encryption_enabled", - "workspaces_vpc_2private_1public_subnets_nat" + "inspector2_is_enabled" ], "Attributes": [ { @@ -4583,16 +3661,11 @@ "Name": "이상행위 분석 및 모니터링", "Description": "내·외부에 의한 침해시도, 개인정보유출 시도, 부정행위 등을 신속하게 탐지·대응할 수 있도록 네트워크 및 데이터 흐름 등을 수집하여 분석하며, 모니터링 및 점검 결과에 따른 사후조치는 적시에 이루어져야 한다.", "Checks": [ - "apigateway_restapi_logging_enabled", - "apigateway_restapi_public", - "apigateway_restapi_tracing_enabled", - "apigatewayv2_api_access_logging_enabled", - "athena_workgroup_logging_enabled", - "bedrock_model_invocation_logging_enabled", - "cloudfront_distributions_logging_enabled", + "cloudtrail_cloudwatch_logging_enabled", "cloudtrail_insights_exist", - "cloudtrail_log_file_validation_enabled", "cloudtrail_logs_s3_bucket_access_logging_enabled", + "cloudtrail_multi_region_enabled_logging_management_events", + "cloudtrail_s3_dataevents_read_enabled", "cloudtrail_s3_dataevents_write_enabled", "cloudtrail_threat_detection_enumeration", "cloudtrail_threat_detection_llm_jacking", @@ -4614,51 +3687,18 @@ "cloudwatch_log_metric_filter_security_group_changes", "cloudwatch_log_metric_filter_sign_in_without_mfa", "cloudwatch_log_metric_filter_unauthorized_api_calls", - "codebuild_project_logging_enabled", - "cognito_user_pool_advanced_security_enabled", "cognito_user_pool_blocks_compromised_credentials_sign_in_attempts", "cognito_user_pool_blocks_potential_malicious_sign_in_attempts", "config_recorder_all_regions_enabled", - "datasync_task_logging_enabled", - "directoryservice_directory_log_forwarding_enabled", - "directoryservice_directory_monitor_notifications", - "documentdb_cluster_cloudwatch_log_export", - "ec2_client_vpn_endpoint_connection_logging_enabled", - "ec2_elastic_ip_shodan", - "ec2_instance_detailed_monitoring_enabled", - "ecs_cluster_container_insights_enabled", - "ecs_task_definitions_logging_enabled", - "eks_control_plane_logging_all_types_enabled", - "elasticbeanstalk_environment_cloudwatch_logging_enabled", - "elasticbeanstalk_environment_enhanced_health_reporting", - "elb_logging_enabled", - "elbv2_logging_enabled", - "glue_etl_jobs_logging_enabled", "guardduty_eks_audit_log_enabled", "guardduty_eks_runtime_monitoring_enabled", "guardduty_no_high_severity_findings", - "kafka_cluster_enhanced_monitoring_enabled", - "mq_broker_logging_enabled", - "neptune_cluster_integration_cloudwatch_logs", - "networkfirewall_logging_enabled", - "opensearch_service_domains_audit_logging_enabled", - "opensearch_service_domains_cloudwatch_logging_enabled", "rds_cluster_critical_event_subscription", - "rds_cluster_integration_cloudwatch_logs", "rds_instance_critical_event_subscription", - "rds_instance_enhanced_monitoring_enabled", "rds_instance_event_subscription_parameter_groups", "rds_instance_event_subscription_security_groups", - "rds_instance_integration_cloudwatch_logs", - "redshift_cluster_audit_logging", - "route53_public_hosted_zones_cloudwatch_logging_enabled", "s3_bucket_event_notifications_enabled", - "s3_bucket_server_access_logging_enabled", - "trustedadvisor_errors_and_warnings", - "vpc_flow_logs_enabled", - "waf_global_webacl_logging_enabled", - "wafv2_webacl_logging_enabled", - "wafv2_webacl_rule_logging_enabled" + "trustedadvisor_errors_and_warnings" ], "Attributes": [ { @@ -4666,7 +3706,7 @@ "Subdomain": "2.11 사고 예방 및 대응", "Section": "2.11.3 이상행위 분석 및 모니터링", "AuditChecklist": [ - "내·외부에 의한 침해시도, 개인정보유출 시도, 부정행위 등 이상행위를 탐지할 수 있도록 주요 정보시스템, 응용프로그램, 네트워크, 보안시스템 등에서 발생한 네트워크 트래픽, 데이터 흐름, 이벤트 로그 등을 수집하여 분석 및 모니터링하고 있는가?", + "내·외부에 의한 침해시도, 개인정보유출 시도, 부정행위 등 이상행위를 탐지할 수 있도록 주요 정보시스템, 응용프로그램, 네트워크, 보안시스템 등에서 발생한 네트워크 트래픽, 데이터 흐름, 이벤트 로그 등을 수집하여 분석 및 모니터링하고 있는가?", "침해시도, 개인정보유출시도, 부정행위 등의 여부를 판단하기 위한 기준 및 임계치를 정의하고 이에 따라 이상행위의 판단 및 조사 등 후속 조치가 적시에 이루어지고 있는가?" ], "RelatedRegulations": [ @@ -4717,20 +3757,16 @@ "Id": "2.11.5", "Name": "사고 대응 및 복구", "Description": "침해사고 및 개인정보 유출 징후나 발생을 인지한 때에는 법적 통지 및 신고 의무를 준수하여야 하며, 절차에 따라 신속하게 대응 및 복구하고 사고분석 후 재발방지 대책을 수립하여 대응체계에 반영하여야 한다.", - "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered" - ], + "Checks": [], "Attributes": [ { "Domain": "2. 보호대책 요구사항", "Subdomain": "2.11 사고 예방 및 대응", "Section": "2.11.5 사고 대응 및 복구", "AuditChecklist": [ - "침해사고 및 개인정보 유출의 징후 또는 발생을 인지한 경우 정의된 침해사고 대응 절차에 따라 신속하게 대응 및 보고가 이루어지고 있는가?", + "침해사고 및 개인정보 유출의 징후 또는 발생을 인지한 경우 정의된 침해사고 대응 절차에 따라 신속하게 대응 및 보고가 이루어지고 있는가?", "개인정보 침해사고 발생 시 관련 법령에 따라 정보주체 통지 및 관계기관 신고 절차를 이행하고 있는가?", - "침해사고가 종결된 후 사고의 원인을 분석하여 그 결과를 보고하고 관련 조직 및 인력과 공유하고 있는가?", + "침해사고가 종결된 후 사고의 원인을 분석하여 그 결과를 보고하고 관련 조직 및 인력과 공유하고 있는가?", "침해사고 분석을 통하여 얻은 정보를 활용하여 유사 사고가 재발하지 않도록 대책을 수립하고 필요한 경우 침해사고 대응절차 등을 변경하고 있는가?" ], "RelatedRegulations": [ @@ -4758,62 +3794,29 @@ "Name": "재해·재난 대비 안전조치", "Description": "자연재해, 통신·전력 장애, 해킹 등 조직의 핵심 서비스 및 시스템의 운영 연속성을 위협할 수 있는 재해 유형을 식별하고, 유형별 예상 피해규모 및 영향을 분석하여야 한다. 또한 복구 목표시간, 복구 목표시점을 정의하고 복구 전략 및 대책, 비상시 복구 조직, 비상연락체계, 복구 절차 등 재해 복구체계를 구축하여야 한다.", "Checks": [ - "account_maintain_current_contact_details", - "account_maintain_different_contact_details_to_security_billing_and_operations", - "account_security_contact_information_is_registered", - "autoscaling_group_capacity_rebalance_enabled", - "autoscaling_group_multiple_az", - "autoscaling_group_multiple_instance_types", - "awslambda_function_vpc_multi_az", "backup_plans_exist", + "backup_reportplans_exist", + "backup_vaults_exist", "cloudfront_distributions_multiple_origin_failover_configured", - "directconnect_connection_redundancy", - "directconnect_virtual_interface_redundancy", - "directoryservice_directory_snapshots_limit", - "dms_instance_multi_az_enabled", + "dlm_ebs_snapshot_lifecycle_policy_exists", "documentdb_cluster_backup_enabled", - "documentdb_cluster_multi_az_enabled", "drs_job_exist", - "dynamodb_accelerator_cluster_multi_az", - "dynamodb_table_autoscaling_enabled", "dynamodb_table_protected_by_backup_plan", "dynamodb_tables_pitr_enabled", "ec2_ebs_volume_protected_by_backup_plan", "ec2_ebs_volume_snapshots_exists", "efs_have_backup_enabled", - "elasticache_redis_cluster_automatic_failover_enabled", "elasticache_redis_cluster_backup_enabled", - "elasticache_redis_cluster_multi_az_enabled", - "elb_cross_zone_load_balancing_enabled", - "elb_is_in_multiple_az", - "elbv2_cross_zone_load_balancing_enabled", - "elbv2_is_in_multiple_az", - "eventbridge_global_endpoint_event_replication_enabled", - "fsx_file_system_copy_tags_to_backups_enabled", - "fsx_windows_file_system_multi_az_enabled", "lightsail_instance_automated_snapshots", - "mq_broker_active_deployment_mode", - "mq_broker_cluster_deployment_mode", "neptune_cluster_backup_enabled", - "neptune_cluster_multi_az", - "opensearch_service_domains_fault_tolerant_data_nodes", - "opensearch_service_domains_fault_tolerant_master_nodes", "rds_cluster_backtrack_enabled", - "rds_cluster_multi_az", "rds_cluster_protected_by_backup_plan", "rds_instance_backup_enabled", - "rds_instance_multi_az", "rds_instance_protected_by_backup_plan", "redshift_cluster_automated_snapshot", - "redshift_cluster_multi_az_enabled", - "s3_bucket_cross_region_replication", "s3_bucket_lifecycle_enabled", "s3_bucket_object_lock", - "s3_bucket_object_versioning", - "sagemaker_endpoint_config_prod_variant_instances", - "vpc_different_regions", - "vpc_endpoint_multi_az_enabled", - "vpc_subnet_different_az" + "s3_bucket_object_versioning" ], "Attributes": [ { @@ -4821,9 +3824,9 @@ "Subdomain": "2.12 재해 복구", "Section": "2.12.1 재해·재난 대비 안전조치", "AuditChecklist": [ - "조직의 핵심 서비스(업무) 연속성을 위협할 수 있는 IT 재해 유형을 식별하고, 유형별 피해규모 및 업무에 미치는 영향을 분석하여 핵심 IT 서비스(업무) 및 시스템을 식별하고 있는가?", + "조직의 핵심 서비스(업무) 연속성을 위협할 수 있는 IT 재해 유형을 식별하고, 유형별 피해규모 및 업무에 미치는 영향을 분석하여 핵심 IT 서비스(업무) 및 시스템을 식별하고 있는가?", "핵심 IT 서비스 및 시스템의 중요도 및 특성에 따른 복구 목표시간, 복구 목표시점을 정의하고 있는가?", - "재해·재난 발생 시에도 핵심 서비스 및 시스템의 연속성을 보장할 수 있도록 복구 전략 및 대책, 비상시 복구 조직, 비상연락체계, 복구 절차 등 재해 복구 계획을 수립 및 이행하고 있는가?" + "재해·재난 발생 시에도 핵심 서비스 및 시스템의 연속성을 보장할 수 있도록 복구 전략 및 대책, 비상시 복구 조직, 비상연락체계, 복구 절차 등 재해 복구 계획을 수립·이행하고 있는가?" ], "RelatedRegulations": [ "개인정보 보호법 제29조(안전조치의무)", @@ -4858,7 +3861,7 @@ "Subdomain": "2.12 재해 복구", "Section": "2.12.2 재해 복구 시험 및 개선", "AuditChecklist": [ - "수립된 IT 재해 복구체계의 실효성을 판단하기 위하여 재해 복구 시험계획을 수립 및 이행하고 있는가?", + "수립된 IT 재해 복구체계의 실효성을 판단하기 위하여 재해 복구 시험계획을 수립·이행하고 있는가?", "시험결과, 정보시스템 환경변화, 법률 등에 따른 변화를 반영할 수 있도록 복구전략 및 대책을 정기적으로 검토·보완하고 있는가?" ], "RelatedRegulations": [], @@ -4893,8 +3896,8 @@ "법정대리인의 동의를 받기 위하여 필요한 최소한의 개인정보만을 수집하고 있으며, 법정대리인이 자격 요건을 갖추고 있는지 확인하는 절차와 방법을 마련하고 있는가?", "만 14세 미만의 아동에게 개인정보 처리와 관련한 사항 등의 고지 시 이해하기 쉬운 양식과 명확하고 알기 쉬운 언어로 표현하고 있는가?", "정보주체 및 법정대리인에게 동의를 받은 기록을 보관하고 있는가?", - "정보주체의 동의 없이 처리할 수 있는 개인정보에 대해서는 그 항목과 처리의 법적 근거를 정보주체의 동의를 받아 처리하는 개인정보와 구분하여 개인정보 처리방침에 공개하거나 정보주체에게 알리고 있는가?", - "정보주체의 동의 없이 개인정보의 추가적인 이용 시 당초 수집 목적과의 관련성, 예측 가능성, 이익 침해 여부, 안전성 확보조치 등의 고려사항에 대한 판단기준을 수립 및 이행하고, 추가적인 이용이 지속적으로 발생하는 경우 고려사항에 대한 판단기준을 개인정보 처리방침에 공개하고 이를 점검하고 있는가?" + "정보주체의 동의 없이 처리할 수 있는 개인정보에 대해서는 그 항목과 처리의 법적 근거를 정보주체의 동의를 받아 처리하는 개인정보와 구분하여 개인정보 처리방침에 공개하거나 정보주체에게 알리고 있는가?", + "정보주체의 동의 없이 개인정보의 추가적인 이용 시 당초 수집 목적과의 관련성, 예측 가능성, 이익 침해 여부, 안전성 확보조치 등의 고려사항에 대한 판단기준을 수립·이행하고, 추가적인 이용이 지속적으로 발생하는 경우 고려사항에 대한 판단기준을 개인정보 처리방침에 공개하고 이를 점검하고 있는가?" ], "RelatedRegulations": [ "개인정보 보호법 제15조(개인정보의 수집·이용), 제22조(동의를 받는 방법), 제22조의2(아동의 개인정보 보호)", @@ -4933,8 +3936,8 @@ "Section": "3.1.2 개인정보 수집 제한", "AuditChecklist": [ "개인정보를 수집하는 경우 그 목적에 필요한 범위에서 최소한의 정보만을 수집하고 있는가?", - "정보주체의 동의를 받아 개인정보를 수집하는 경우 필요한 최소한의 정보 외의 개인정보 수집에는 동의하지 않을 수 있다는 사실을 구체적으로 알리고 있는가?", - "정보주체가 수집 목적에 필요한 최소한의 정보 이외의 개인정보 수집에 동의하지 않는다는 이유로 서비스 또는 재화의 제공을 거부하지 않도록 하고 있는가?" + "정보주체의 동의를 받아 개인정보를 수집하는 경우 필요한 최소한의 정보 외의 개인정보 수집에는 동의하지 않을 수 있다는 사실을 구체적으로 알리고 있는가?", + "정보주체가 수집 목적에 필요한 최소한의 정보 이외의 개인정보 수집에 동의하지 않는다는 이유로 서비스 또는 재화의 제공을 거부하지 않도록 하고 있는가?" ], "RelatedRegulations": [ "개인정보 보호법 제16조(개인정보의 수집제한), 제22조(동의를 받는 방법)" @@ -5001,7 +4004,7 @@ "Subdomain": "3.1 개인정보 수집 시 보호조치", "Section": "3.1.4 민감정보 및 고유식별정보의 처리 제한", "AuditChecklist": [ - "민감정보는 정보주체로부터 별도의 동의를 받거나 관련 법령에 근거가 있는 경우에만 처리하고 있는가?", + "민감정보는 정보주체로부터 별도의 동의를 받거나 관련 법령에 근거가 있는 경우에만 처리하고 있는가?", "고유식별정보(주민등록번호 제외)는 정보주체로부터 별도의 동의를 받거나 관련 법령에 구체적인 근거가 있는 경우에만 처리하고 있는가?", "재화 또는 서비스를 제공하는 과정에서 공개되는 정보에 정보주체의 민감정보가 포함됨으로써 사생활 침해의 위험성이 있다고 판단하는 때에는 재화 또는 서비스의 제공 전에 민감정보의 공개 가능성 및 비공개를 선택하는 방법을 정보주체가 알아보기 쉽게 알리고 있는가?" ], @@ -5098,7 +4101,7 @@ { "Id": "3.1.7", "Name": "마케팅 목적의 개인정보 수집·이용", - "Description": "재화나 서비스의 홍보, 판매 권유, 광고성 정보전송 등 마케팅 목적으로 개인정보를 수집 및이용하는 경우 그 목적을 정보주체가 명확하게 인지할 수 있도록 고지하고 동의를 받아야 한다.", + "Description": "재화나 서비스의 홍보, 판매 권유, 광고성 정보전송 등 마케팅 목적으로 개인정보를 수집·이용하는 경우 그 목적을 정보주체가 명확하게 인지할 수 있도록 고지하고 동의를 받아야 한다.", "Checks": [], "Attributes": [ { @@ -5157,16 +4160,7 @@ "개인정보 흐름표·흐름도", "개인정보파일 등록 현황", "개인정보파일 관리대장", - "개인정보 처리방침에 관한 사항을 기록한 개인정보파일", - "「조세범처벌법」에 따른 범칙행위 조사 및 「관세법」에 따른 범칙행위 조사에 관한 사항을 기록한 개인정보파일", - "일회성으로 운영되는 파일 등 지속적으로 관리할 필요가 낮다고 인정되어 대통령령으로 정하는 개인정보파일", - "회의 참석 수당 지급, 자료·물품의 송부, 금전의 정산 등 단순 업무 수행을 위해 운영되는 개인정보파일로서 지속적 관리 필요성이 낮은 개인정보파일", - "공중위생 등 공공의 안전과 안녕을 위하여 긴급히 필요한 경우로서 일시적으로 처리되는 개인정보파일", - "그 밖에 일회적 업무 처리만을 위해 수집된 개인정보파일로서 저장되거나 기록되지 않는 개인정보파일", - "다른 법령에 따라 비밀로 분류된 개인정보파일", - "국가안전보장과 관련된 정보 분석을 목적으로 수집 또는 제공 요청되는 개인정보파일", - "영상정보처리기기를 통하여 처리되는 개인영상정보파일", - "「금융실명거래 및 비밀보장에 관한 법률」에 따른 금융기관이 금융업무 취급을 위하여 보유하는 개인정보파일" + "개인정보 처리방침" ], "NonComplianceCases": [ "사례 1 : 개인정보파일을 홈페이지의 개인정보파일 등록 메뉴를 통하여 목록을 관리하고 있으나, 그 중 일부 홈페이지 서비스와 관련된 개인정보파일의 내용이 개인정보 처리방침에 누락되어 있는 경우", @@ -5188,7 +4182,7 @@ "Subdomain": "3.2 개인정보 보유 및 이용 시 보호조치", "Section": "3.2.2 개인정보 품질보장", "AuditChecklist": [ - "개인정보를 최신의 상태로 정확하게 유지하기 위한 절차 및 방안을 수립·이행하고 있는가?", + "개인정보를 최신의 상태로 정확하게 유지하기 위한 절차 및 방안을 수립·이행하고 있는가?", "정보주체가 본인의 개인정보에 대하여 정확성, 완전성 및 최신성을 유지할 수 있는 방법을 제공하고 있는가?" ], "RelatedRegulations": [ @@ -5325,7 +4319,7 @@ "개인정보를 제3자에게 제공하는 경우 제공 목적에 맞는 최소한의 개인정보 항목으로 제한하고 있는가?", "개인정보를 제3자에게 제공하는 경우 안전한 절차와 방법을 통해 제공하고 제공 내역을 기록하여 보관하고 있는가?", "제3자에게 개인정보의 접근을 허용하는 경우 개인정보를 안전하게 보호하기 위한 보호절차에 따라 통제하고 있는가?", - "정보주체의 동의 없이 개인정보의 추가적인 제공 시 당초 수집 목적과의 관련성, 예측 가능성, 이익 침해 여부, 안전성 확보조치 등의 고려사항에 대한 판단기준을 수립 및 이행하고, 추가적인 제공이 지속적으로 발생하는 경우 고려사항에 대한 판단기준을 개인정보 처리방침에 공개하고 이를 점검하고 있는가?" + "정보주체의 동의 없이 개인정보의 추가적인 제공 시 당초 수집 목적과의 관련성, 예측 가능성, 이익 침해 여부, 안전성 확보조치 등의 고려사항에 대한 판단기준을 수립 및 이행하고, 추가적인 제공이 지속적으로 발생하는 경우 고려사항에 대한 판단기준을 개인정보 처리방침에 공개하고 이를 점검하고 있는가?" ], "RelatedRegulations": [ "개인정보 보호법 제17조(개인정보의 제공), 제22조(동의를 받는 방법)", @@ -5552,7 +4546,7 @@ "Subdomain": "3.5 정보주체 권리보호", "Section": "3.5.2 정보주체 권리보장", "AuditChecklist": [ - "정보주체 또는 그 대리인이 개인정보에 대한 열람, 정정·삭제, 처리정지 및 동의 철회 등(이하 '열람등요구'라 함)을 개인정보 수집방법·절차보다 어렵지 아니하도록 권리 행사 방법 및 절차를 마련하여 공개하고 있는가?", + "정보주체 또는 그 대리인이 개인정보에 대한 열람, 정정·삭제, 처리정지 및 동의 철회 등(이하 '열람등요구'라 함)을 개인정보 수집방법·절차보다 어렵지 아니하도록 권리 행사 방법 및 절차를 마련하여 공개하고 있는가?", "정보주체 또는 그 대리인이 개인정보 열람등요구를 하는 경우 기간 내에 열람등요구에 따른 필요한 조치를 하고 있는가?", "정보주체 또는 그 대리인이 개인정보 수집·이용·제공 등의 동의를 철회하는 경우 지체 없이 수집된 개인정보를 파기하는 등 필요한 조치를 취하고 있는가?", "정보주체의 열람등요구에 대한 조치에 불복이 있는 경우 이의를 제기할 수 있도록 필요한 절차를 마련하여 안내하고 있는가?", @@ -5602,11 +4596,11 @@ "개인정보 이용·제공 내역 통지 양식 및 문구" ], "NonComplianceCases": [ - "사례 1 : 전년도 말 기준 직전 3개월 간 일일 평균 저장·관리하고 있는 개인정보가 100만명 이상으로서 개인정보 이용제공 내역 통지 의무 대상자에 해당 됨에도 불구하고 금년도에 개인정보 이용 및 내역을 통지하지 않은 경우", + "사례 1 : 전년도 말 기준 직전 3개월 간 일일 평균 저장·관리하고 있는 개인정보가 100만명 이상으로서 개인정보 이용제공 내역 통지 의무 대상자에 해당 됨에도 불구하고 금년도에 개인정보 이용·내역을 통지하지 않은 경우", "사례 2 : 개인정보 이용·제공 내역을 개별 정보주체에게 직접적으로 통지하는 대신 홈페이지에서 단순 팝업창이나 별도 공지사항으로 안내만 한 경우" ] } ] } ] -} +} \ No newline at end of file From 2854f8405cb9f707d8c4d0f4b9c0d95107d81812 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah Date: Wed, 13 Aug 2025 14:29:47 +0530 Subject: [PATCH 17/30] fix: simplify error handling to use only error.message (#8518) Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> --- ui/app/api/lighthouse/analyst/route.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/app/api/lighthouse/analyst/route.ts b/ui/app/api/lighthouse/analyst/route.ts index 6bbf076f6e..435f063c35 100644 --- a/ui/app/api/lighthouse/analyst/route.ts +++ b/ui/app/api/lighthouse/analyst/route.ts @@ -86,14 +86,12 @@ export async function POST(req: Request) { } controller.close(); } catch (error) { - const errorName = - error instanceof Error ? error.constructor.name : "UnknownError"; const errorMessage = error instanceof Error ? error.message : String(error); controller.enqueue({ id: "error-" + Date.now(), role: "assistant", - content: `[LIGHTHOUSE_ANALYST_ERROR]: ${errorName}: ${errorMessage}`, + content: `[LIGHTHOUSE_ANALYST_ERROR]: ${errorMessage}`, }); controller.close(); } From 81478dfed3fdf2fdfde7eba6d8238ef702cd4159 Mon Sep 17 00:00:00 2001 From: Hugo Pereira Brito <101209179+HugoPBrito@users.noreply.github.com> Date: Wed, 13 Aug 2025 16:45:36 +0200 Subject: [PATCH 18/30] fix(compliance): GitHub CIS 1.0 (#8519) --- prowler/CHANGELOG.md | 1 + prowler/compliance/github/cis_1.0_github.json | 1307 +++++++++-------- ...mpliance_json_from_csv_for_cis10_github.py | 19 +- 3 files changed, 736 insertions(+), 591 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index e330cfd745..7f66a914eb 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Azure `app_http_logs_enabled` check false positives [(#8507)](https://github.com/prowler-cloud/prowler/pull/8507) - Azure `storage_geo_redundant_enabled` check false positives [(#8504)](https://github.com/prowler-cloud/prowler/pull/8504) - AWS `kafka_cluster_is_public` check false positives [(#8514)](https://github.com/prowler-cloud/prowler/pull/8514) +- GitHub CIS 1.0 Compliance Reports [(#8519)](https://github.com/prowler-cloud/prowler/pull/8519) --- diff --git a/prowler/compliance/github/cis_1.0_github.json b/prowler/compliance/github/cis_1.0_github.json index bc01cfccdc..cf58f60452 100644 --- a/prowler/compliance/github/cis_1.0_github.json +++ b/prowler/compliance/github/cis_1.0_github.json @@ -6,11 +6,12 @@ "Requirements": [ { "Id": "1.1.1", - "Description": "Ensure any changes to code are tracked in a version control platform", + "Description": "Manage all code projects in a version control platform.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Manage all code projects in a version control platform.", @@ -19,18 +20,19 @@ "RemediationProcedure": "Upload existing code projects to a dedicated Github organization and repositories and create an identity for each active team member who might contribute or need access to it.", "AuditProcedure": "Ensure that all code activity is managed through Github repository for every micro-service or application developed by an organization.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.1.2", - "Description": "Ensure any change to code can be traced back to its associated task", + "Description": "Use a task management system to trace any code back to its associated task.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Use a task management system to trace any code back to its associated task.", @@ -39,829 +41,869 @@ "RemediationProcedure": "Use a task management system to manage tasks as the starting point for each code change. Whether it is a new feature, bug fix, or security fix - all should originate from a dedicated task (ticket) in your organization's task management system. These tasks should also be linked to the code changes themselves in a way that is easy to follow: from code to task, and from task back to code.", "AuditProcedure": "Ensure every code change can be traced back to its origin task in a task management system.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.1.3", - "Description": "Ensure any change to code receives approval of two strongly authenticated users", + "Description": "Ensure that every code change is reviewed and approved by two authorized contributors who are both strongly authenticated - using Multi-Factor Authentication (MFA), from the team relevant to the code change.", "Checks": [ "repository_default_branch_requires_multiple_approvals" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Automated", "Description": "Ensure that every code change is reviewed and approved by two authorized contributors who are both strongly authenticated - using Multi-Factor Authentication (MFA), from the team relevant to the code change.", "RationaleStatement": "To prevent malicious or unauthorized code changes, the first layer of protection is the process of code review. This process involves engineer teammates reviewing each other's code for errors, optimizations, and general knowledge-sharing. With proper peer reviews in place, an organization can detect unwanted code changes very early in the process of release. In order to help facilitate code review, companies should employ automation to verify that every code change has been reviewed and approved by at least two team members before it is pushed into the code base. These team members should be from the team that is related to the code change, so it will be a meaningful review.", "ImpactStatement": "To enforce a code review requirement, verification for a minimum of two reviewers must be put into place. This will ensure new code will not be able to be pushed to the code base before it has received two independent approvals.", - "RemediationProcedure": "For every code repository in use, perform the next steps to require two approvals from the specific code repository team in order to push new code to the code base:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you added the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Check **Require a pull request before merging** and **Require approvals**, and set **Required number of approvals before merging** to 2.\n 5. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, perform the next steps to verify that two approvals from the specific code repository team are required to push new code to the code base:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require a pull request before merging** and **Require approvals** are checked, and verify that **Required number of approvals before merging** is set to 2.", + "RemediationProcedure": "For every code repository in use, perform the next steps to require two approvals from the specific code repository team in order to push new code to the code base:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you added the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Check **Require a pull request before merging** and **Require approvals**, and set **Required number of approvals before merging** to 2.\n5. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, perform the next steps to verify that two approvals from the specific code repository team are required to push new code to the code base:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require a pull request before merging** and **Require approvals** are checked, and verify that **Required number of approvals before merging** is set to 2.", "AdditionalInformation": "", - "DefaultValue": "0", - "References": "" + "References": "", + "DefaultValue": "0" } ] }, { "Id": "1.1.4", - "Description": "Ensure previous approvals are dismissed when updates are introduced to a code change proposal", + "Description": "Ensure that when a proposed code change is updated, previous approvals are declined, and new approvals are required.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure that when a proposed code change is updated, previous approvals are declined, and new approvals are required.", "RationaleStatement": "An approval process is necessary when code changes are suggested. Through this approval process, however, changes can still be made to the original proposal even after some approvals have already been given. This means malicious code can find its way into the code base even if the organization has enforced a review policy. To ensure this is not possible, outdated approvals must be declined when changes to the suggestion are introduced.", "ImpactStatement": "If new code changes are pushed to a specific proposal, all previously accepted code change proposals must be declined.", - "RemediationProcedure": "For each code repository in use, perform the next steps to enforce dismissal of given approvals to code change suggestions if those suggestions were updated:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you added the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require pull request reviews before merging** and then **Dismiss stale pull request approvals when new commits are pushed**.\n 5. Click **Create** or **Save changes**.", - "AuditProcedure": "For each code repository in use, perform the next steps to verify that each updated code suggestion declines the previously received approvals:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require a pull request before merging** is checked, and verify that **Dismiss stale pull request approvals when new commits are pushed** is checked.", + "RemediationProcedure": "For each code repository in use, perform the next steps to enforce dismissal of given approvals to code change suggestions if those suggestions were updated:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you added the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require pull request reviews before merging** and then **Dismiss stale pull request approvals when new commits are pushed**.\n5. Click **Create** or **Save changes**.", + "AuditProcedure": "For each code repository in use, perform the next steps to verify that each updated code suggestion declines the previously received approvals:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require a pull request before merging** is checked, and verify that **Dismiss stale pull request approvals when new commits are pushed** is checked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.1.5", - "Description": "Ensure there are restrictions on who can dismiss code change reviews", + "Description": "Only trusted users should be allowed to dismiss code change reviews.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Only trusted users should be allowed to dismiss code change reviews.", "RationaleStatement": "Dismissing a code change review permits users to merge new suggested code changes without going through the standard process of approvals. Controlling who can perform this action will prevent malicious actors from simply dismissing the required reviews to code changes and merging malicious or dysfunctional code into the code base.", - "ImpactStatement": "In cases where a code change proposal has been updated since it was last reviewed and the person who reviewed it isn't available for approval, a general collaborator would not be able to merge their code changes until a user with \"dismiss review\" abilities could dismiss the open review.\n \n\n Users who are not allowed to dismiss code change reviews will not be permitted to do so, and thus are unable to waive the standard flow of approvals.", - "RemediationProcedure": "For each code repository in use, perform the next steps to restrict dismissal of code changes reviews unless it is necessary:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you added the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 4. Select **Require pull request reviews before merging** and **Restrict who can dismiss pull request reviews**.\n 5. Do not add any user or team unless it is obligatory. If it is obligatory, carefully select the users or teams whom you trust with the ability to dismiss code change reviews.\n 6. Click **Create** or **Save changes**.", - "AuditProcedure": "For each code repository in use, perform the next steps to verify that only trusted users are allowed to dismiss code change reviews: \n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 4. Verify that **Require a pull request before merging** and **Restrict who can dismiss pull request reviews** is checked.\n 5. Verify that no users and teams are specified except for organization and repository admins. If it is obligatory, verify that the users or teams specified were carefully selected to be trusted with the ability to dismiss code change reviews.", + "ImpactStatement": "In cases where a code change proposal has been updated since it was last reviewed and the person who reviewed it isn't available for approval, a general collaborator would not be able to merge their code changes until a user with \"dismiss review\" abilities could dismiss the open review.\n\nUsers who are not allowed to dismiss code change reviews will not be permitted to do so, and thus are unable to waive the standard flow of approvals.", + "RemediationProcedure": "For each code repository in use, perform the next steps to restrict dismissal of code changes reviews unless it is necessary:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you added the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n4. Select **Require pull request reviews before merging** and **Restrict who can dismiss pull request reviews**.\n5. Do not add any user or team unless it is obligatory. If it is obligatory, carefully select the users or teams whom you trust with the ability to dismiss code change reviews.\n6. Click **Create** or **Save changes**.", + "AuditProcedure": "For each code repository in use, perform the next steps to verify that only trusted users are allowed to dismiss code change reviews: \n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n4. Verify that **Require a pull request before merging** and **Restrict who can dismiss pull request reviews** is checked.\n5. Verify that no users and teams are specified except for organization and repository admins. If it is obligatory, verify that the users or teams specified were carefully selected to be trusted with the ability to dismiss code change reviews.", "AdditionalInformation": "", - "DefaultValue": "By default, all users who have write access to the code repository are able to dismiss code change reviews.", - "References": "" + "References": "", + "DefaultValue": "By default, all users who have write access to the code repository are able to dismiss code change reviews." } ] }, { "Id": "1.1.6", - "Description": "Ensure code owners are set for extra sensitive code or configuration", + "Description": "Code owners are trusted users that are responsible for reviewing and managing an important piece of code or configuration. An organization is advised to set code owners for every extremely sensitive code or configuration.", "Checks": [ "repository_has_codeowners_file" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Code owners are trusted users that are responsible for reviewing and managing an important piece of code or configuration. An organization is advised to set code owners for every extremely sensitive code or configuration.", "RationaleStatement": "Configuring code owners protects data by verifying that trusted users will notice and review every edit, thus preventing unwanted or malicious changes from potentially compromising sensitive code or configurations.", "ImpactStatement": "Code owner users will receive notifications for every change that occurs to the code and subsequently added as reviewers of pull requests automatically.", - "RemediationProcedure": "In every code repository create a CODEOWNERS file in the root, docs/, or .github/ directory of the repository.\n In the file, specify codeowners for the .github/workflows/ directory atleast. Specify organization members you trust. For example:\n ```\n .github/workflows/ @user1 @user2\n ```", - "AuditProcedure": "In every code repository, verify that a file named CODEOWNERS exists in the root, docs/, or .github/ directory of the repository.\n In the CODEOWNERS file, verify that the users specified are users you trust.", + "RemediationProcedure": "In every code repository create a CODEOWNERS file in the root, docs/, or .github/ directory of the repository.\nIn the file, specify codeowners for the .github/workflows/ directory atleast. Specify organization members you trust. For example:\n```\n.github/workflows/ @user1 @user2\n```", + "AuditProcedure": "In every code repository, verify that a file named CODEOWNERS exists in the root, docs/, or .github/ directory of the repository.\nIn the CODEOWNERS file, verify that the users specified are users you trust.", "AdditionalInformation": "", - "DefaultValue": "None", - "References": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners" + "References": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners", + "DefaultValue": "None" } ] }, { "Id": "1.1.7", - "Description": "Ensure code owner's review is required when a change affects owned code", + "Description": "Ensure trusted code owners are required to review and approve any code change proposal made to their respective owned areas in the code base.", "Checks": [ "repository_default_branch_requires_codeowners_review" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure trusted code owners are required to review and approve any code change proposal made to their respective owned areas in the code base.", "RationaleStatement": "Configuring code owners ensures that no code, especially code which could prove malicious, will slip into the source code or configuration files of a repository. This allows an organization to mark areas in the code base that are especially sensitive or more prone to an attack. It can also enforce review by specific individuals who are designated as owners to those areas so that they may filter out unauthorized or unwanted changes beforehand.", "ImpactStatement": "If an organization enforces code owner-based reviews, some code change proposals would not be able to be merged to the codebase before specific, trusted individuals approve them.", - "RemediationProcedure": "For every code repository in use, perform the following steps to require code owners' approvals for each change proposal related to code they own:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require pull request reviews before merging** and **Require review from Code Owners**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, perform the following steps to verify that code owners are required to review all code change proposals relevant to areas they own before code merge:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 4. Ensure that **Require a pull request before merging** and **Require review from Code Owners** are checked.", + "RemediationProcedure": "For every code repository in use, perform the following steps to require code owners' approvals for each change proposal related to code they own:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require pull request reviews before merging** and **Require review from Code Owners**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, perform the following steps to verify that code owners are required to review all code change proposals relevant to areas they own before code merge:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n4. Ensure that **Require a pull request before merging** and **Require review from Code Owners** are checked.", "AdditionalInformation": "", - "DefaultValue": "Code owners are not required to review changes by default.", - "References": "" + "References": "", + "DefaultValue": "Code owners are not required to review changes by default." } ] }, { "Id": "1.1.8", - "Description": "Ensure inactive branches are periodically reviewed and removed", + "Description": "Keep track of code branches that are inactive for a lengthy period of time and periodically remove them.", "Checks": [ "repository_inactive_not_archived", "repository_branch_delete_on_merge_enabled" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Keep track of code branches that are inactive for a lengthy period of time and periodically remove them.", "RationaleStatement": "Git branches that have been inactive (i.e., no new changes introduced) for a long period of time are enlarging the surface of attack for malicious code injection, sensitive data leaks, and CI pipeline exploitation. They potentially contain outdated dependencies which may leave them highly vulnerable. They are more likely to be improperly managed, and could possibly be accessed by a large number of members of the organization.", "ImpactStatement": "Removing inactive Git branches means that any code changes they contain would be removed along with them, thus work done in the past might not be accessible after auditing for inactivity.", - "RemediationProcedure": "For each code repository in use, review existing Git branches and remove those which have not been active for a period of time by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Above the list of files, click **Branches**.\n 3. Use the navigation at the top of the page to view the Stale branches. The Stale view shows all branches that no one has committed to in the last three months, ordered by the branches with the oldest commits first.\n 4. For each branch listed, either delete it by clicking the trash bin icon, or find the valid reason it still exists.\n \n\n You can perform the next steps to prevent pull request branches from becoming stale branches:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click Settings.\n 3. Under \"Pull Requests\", select **Automatically delete head branches**.", - "AuditProcedure": "For each code repository in use, verify that all existing Git branches are active or have yet to be checked for inactivity by performing the next steps:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Above the list of files, click **Branches**.\n 3. Use the navigation at the top of the page to view the Stale branches. The Stale view shows all branches that no one has committed to in the last three months, ordered by the branches with the oldest commits first.\n 4. If the list is empty, you are compliant. If the list is not empty, but there is a valid reason the branches listed are not deleted, you are compliant.", + "RemediationProcedure": "For each code repository in use, review existing Git branches and remove those which have not been active for a period of time by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Above the list of files, click **Branches**.\n3. Use the navigation at the top of the page to view the Stale branches. The Stale view shows all branches that no one has committed to in the last three months, ordered by the branches with the oldest commits first.\n4. For each branch listed, either delete it by clicking the trash bin icon, or find the valid reason it still exists.\n\nYou can perform the next steps to prevent pull request branches from becoming stale branches:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click Settings.\n3. Under \"Pull Requests\", select **Automatically delete head branches**.", + "AuditProcedure": "For each code repository in use, verify that all existing Git branches are active or have yet to be checked for inactivity by performing the next steps:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Above the list of files, click **Branches**.\n3. Use the navigation at the top of the page to view the Stale branches. The Stale view shows all branches that no one has committed to in the last three months, ordered by the branches with the oldest commits first.\n4. If the list is empty, you are compliant. If the list is not empty, but there is a valid reason the branches listed are not deleted, you are compliant.", "AdditionalInformation": "", - "DefaultValue": "By default, newly opened Git branches would never be removed, regardless of activity or inactivity.", - "References": "" + "References": "", + "DefaultValue": "By default, newly opened Git branches would never be removed, regardless of activity or inactivity." } ] }, { "Id": "1.1.9", - "Description": "Ensure all checks have passed before merging new code", + "Description": "Before a code change request can be merged to the code base, all predefined checks must successfully pass.", "Checks": [ "repository_default_branch_status_checks_required" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Before a code change request can be merged to the code base, all predefined checks must successfully pass.", "RationaleStatement": "On top of manual reviews of code changes, a code protect should contain a set of prescriptive checks which validate each change. Organizations should enforce those status checks so that changes can only be introduced if all checks have successfully passed. This set of checks should serve as the absolute quality, stability, and security conditions which must be met in order to merge new code to a project.", "ImpactStatement": "Code changes in which all checks do not pass successfully would not be able to be pushed into the code base of the specific code repository.", - "RemediationProcedure": "For each code repository in use, require all status checks to pass before permitting a merge of new code by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", check if there is a rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require status checks to pass before merging**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For each code repository in use, verify that status checks are required to pass before allowing any code change proposal merge by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require status checks to pass before merging** is checked.", + "RemediationProcedure": "For each code repository in use, require all status checks to pass before permitting a merge of new code by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", check if there is a rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require status checks to pass before merging**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For each code repository in use, verify that status checks are required to pass before allowing any code change proposal merge by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require status checks to pass before merging** is checked.", "AdditionalInformation": "", - "DefaultValue": "By default, no checks are defined per project, and thus no enforcement of checks is made.", - "References": "" + "References": "", + "DefaultValue": "By default, no checks are defined per project, and thus no enforcement of checks is made." } ] }, { "Id": "1.1.10", - "Description": "Ensure open Git branches are up to date before they can be merged into code base", + "Description": "Organizations should make sure each suggested code change is in full sync with the existing state of its origin code repository before allowing merging.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Organizations should make sure each suggested code change is in full sync with the existing state of its origin code repository before allowing merging.", "RationaleStatement": "Git branches can easily become outdated since the origin code repository is constantly being edited. This means engineers working on separate code branches can accidentally include outdated code with potential security issues which might have already been fixed, overriding the potential solutions for those security issues when merging their own changes.", "ImpactStatement": "If enforced, outdated branches would not be able to be merged into their origin repository without first being updated to contain any recent changes.", - "RemediationProcedure": "For each code repository in use, enforce a policy to only allow merging open branches if they are current with the latest change from their original repository by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require status checks to pass before merging** and **Require branches to be up to date before merging**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For each code repository in use, verify that open branches must be updated before merging is permitted by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require status checks to pass before merging** and **Require branches to be up to date before merging** are checked.", + "RemediationProcedure": "For each code repository in use, enforce a policy to only allow merging open branches if they are current with the latest change from their original repository by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require status checks to pass before merging** and **Require branches to be up to date before merging**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For each code repository in use, verify that open branches must be updated before merging is permitted by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require status checks to pass before merging** and **Require branches to be up to date before merging** are checked.", "AdditionalInformation": "", - "DefaultValue": "By default, there is no requirement to update a branch before merging it.", - "References": "https://github.blog/changelog/2022-02-03-more-ways-to-keep-your-pull-request-branch-up-to-date/" + "References": "https://github.blog/changelog/2022-02-03-more-ways-to-keep-your-pull-request-branch-up-to-date/", + "DefaultValue": "By default, there is no requirement to update a branch before merging it." } ] }, { "Id": "1.1.11", - "Description": "Ensure all open comments are resolved before allowing code change merging", + "Description": "Organizations should enforce a \"no open comments\" policy before allowing code change merging.", "Checks": [ "repository_default_branch_requires_conversation_resolution" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Organizations should enforce a \"no open comments\" policy before allowing code change merging.", "RationaleStatement": "In an open code change proposal, reviewers can leave comments containing their questions and suggestions. These comments can also include potential bugs and security issues. Requiring all comments on a code change proposal to be resolved before it can be merged ensures that every concern is properly addressed or acknowledged before the new code changes are introduced to the code base.", "ImpactStatement": "Code change proposals containing open comments would not be able to be merged into the code base.", - "RemediationProcedure": "For each code repository in use, require open comments to be resolved before the relevant code change can be merged by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require conversation resolution before merging**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, verify that each merged code change does not contain open, unattended comments by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require conversation resolution before merging** is checked.", + "RemediationProcedure": "For each code repository in use, require open comments to be resolved before the relevant code change can be merged by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require conversation resolution before merging**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, verify that each merged code change does not contain open, unattended comments by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require conversation resolution before merging** is checked.", "AdditionalInformation": "", - "DefaultValue": "By default, code changes with open comments on them are able to be merged into the code base.", - "References": "" + "References": "", + "DefaultValue": "By default, code changes with open comments on them are able to be merged into the code \nbase." } ] }, { "Id": "1.1.12", - "Description": "Ensure verification of signed commits for new changes before merging", + "Description": "Ensure every commit in a pull request is signed and verified before merging.", "Checks": [ "repository_default_branch_requires_signed_commits" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Ensure every commit in a pull request is signed and verified before merging.", "RationaleStatement": "Signing commits, or requiring to sign commits, gives other users confidence about the origin of a specific code change. It ensures that the author of the change is not hidden and is verified by the version control system, thus the change comes from a trusted source.", "ImpactStatement": "Pull requests with unsigned commits cannot be merged.", - "RemediationProcedure": "For each repository in use, enforce the branch protection rule of requiring signed commits, and make sure only signed commits are capable of merging by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require signed commits**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "Ensure only signed commits can be merged for every branch, especially the main branch, via branch protection rules by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require signed commits** is checked.", + "RemediationProcedure": "For each repository in use, enforce the branch protection rule of requiring signed commits, and make sure only signed commits are capable of merging by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require signed commits**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "Ensure only signed commits can be merged for every branch, especially the main branch, via branch protection rules by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require signed commits** is checked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits" + "References": "https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits", + "DefaultValue": "" } ] }, { "Id": "1.1.13", - "Description": "Ensure linear history is required", + "Description": "Linear history is the name for Git history where all commits are listed in chronological order, one after another. Such history exists if a pull request is merged either by rebase merge (re-order the commits history) or squash merge (squashes all commits to one). Ensure that linear history is required by requiring the use of rebase or squash merge when merging a pull request.", "Checks": [ "repository_default_branch_requires_linear_history" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Linear history is the name for Git history where all commits are listed in chronological order, one after another. Such history exists if a pull request is merged either by rebase merge (re-order the commits history) or squash merge (squashes all commits to one). Ensure that linear history is required by requiring the use of rebase or squash merge when merging a pull request.", "RationaleStatement": "Enforcing linear history produces a clear record of activity, and as such it offers specific advantages: it is easier to follow, easier to revert a change, and bugs can be found more easily.", "ImpactStatement": "Pull request cannot be merged except squash or rebase merge.", - "RemediationProcedure": "For every code repository in use, perform the following steps to require linear history and/or allow only rebase merge and squash merge:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Require linear history**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, perform the following steps to verify that linear history is required and/or that only squash merge and rebase merge are allowed:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Require linear history** is checked.", + "RemediationProcedure": "For every code repository in use, perform the following steps to require linear history and/or allow only rebase merge and squash merge:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Require linear history**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, perform the following steps to verify that linear history is required and/or that only squash merge and rebase merge are allowed:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Require linear history** is checked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.1.14", - "Description": "Ensure branch protection rules are enforced for administrators", + "Description": "Ensure administrators are subject to branch protection rules.", "Checks": [ "repository_default_branch_protection_applies_to_admins" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure administrators are subject to branch protection rules.", "RationaleStatement": "Administrators by default are excluded from any branch protection rules. This means these privileged users (both on the repository and organization levels) are not subject to protections meant to prevent untrusted code insertion, including malicious code. This is extremely important since administrator accounts are often targeted for account hijacking due to their privileged role.", "ImpactStatement": "Administrator users won't be able to push code directly to the protected branch without being compliant with listed branch protection rules.", - "RemediationProcedure": "For every code repository in use, enforce branch protection rules on administrators as well, by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Do not allow bypassing the above settings**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, validate branch protection rules also apply to administrator accounts by performing the next steps:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Do not allow bypassing the above settings** is checked.", + "RemediationProcedure": "For every code repository in use, enforce branch protection rules on administrators as well, by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Do not allow bypassing the above settings**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, validate branch protection rules also apply to administrator accounts by performing the next steps:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Do not allow bypassing the above settings** is checked.", "AdditionalInformation": "", - "DefaultValue": "Administrator accounts are not subject to branch protection rules by default.", - "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule" + "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule", + "DefaultValue": "Administrator accounts are not subject to branch protection rules by default." } ] }, { "Id": "1.1.15", - "Description": "Ensure pushing or merging of new code is restricted to specific individuals or teams", + "Description": "Ensure that only trusted users can push or merge new code to protected branches.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Ensure that only trusted users can push or merge new code to protected branches.", "RationaleStatement": "Requiring that only trusted users may push or merge new changes reduces the risk of unverified code, especially malicious code, to a protected branch by reducing the number of trusted users who are capable of doing such.", "ImpactStatement": "Only administrators and trusted users can push or merge to the protected branch.", - "RemediationProcedure": "For every code repository in use, allow only trusted and responsible users to push or merge new code by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4.Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Select **Restrict who can push to matching branches** and choose trusted and responsible users and teams who will have the permission to do so. \n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, ensure only trusted and responsible users can push or merge new code by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Restrict who can push to matching branches** is checked and that only trusted and responsible users and teams are selected.", + "RemediationProcedure": "For every code repository in use, allow only trusted and responsible users to push or merge new code by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4.Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Select **Restrict who can push to matching branches** and choose trusted and responsible users and teams who will have the permission to do so. \n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, ensure only trusted and responsible users can push or merge new code by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Restrict who can push to matching branches** is checked and that only trusted and responsible users and teams are selected.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule" + "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule", + "DefaultValue": "" } ] }, { "Id": "1.1.16", - "Description": "Ensure force push code to branches is denied", + "Description": "The \"Force Push\" option allows users with \"Push\" permissions to force their changes directly to the branch without a pull request, and thus should be disabled.", "Checks": [ "repository_default_branch_disallows_force_push" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "The \"Force Push\" option allows users with \"Push\" permissions to force their changes directly to the branch without a pull request, and thus should be disabled.", "RationaleStatement": "The \"Force Push\" option allows users to override the existing code with their own code. This can lead to both intentional and unintentional data loss, as well as data infection with malicious code. Disabling the \"Force Push\" option prohibits users from forcing their changes to the master branch, which ultimately prevents malicious code from entering source code.", "ImpactStatement": "Users cannot force push to protected branches.", - "RemediationProcedure": "For each repository in use, block the option to \"Force Push\" code by performing the following: \n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Uncheck **Allow force pushes**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For every code repository in use, validate that no one can force push code by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Allow force pushes** is not checked.", + "RemediationProcedure": "For each repository in use, block the option to \"Force Push\" code by performing the following: \n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Uncheck **Allow force pushes**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For every code repository in use, validate that no one can force push code by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Allow force pushes** is not checked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule" + "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule", + "DefaultValue": "" } ] }, { "Id": "1.1.17", - "Description": "Ensure branch deletions are denied", + "Description": "Ensure that users with only push access are incapable of deleting a protected branch.", "Checks": [ "repository_default_branch_deletion_disabled" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure that users with only push access are incapable of deleting a protected branch.", "RationaleStatement": "When enabling deletion of a protected branch, any user with at least push access to the repository can delete a branch. This can be potentially dangerous, as a simple human mistake or a hacked account can lead to data loss if a branch is deleted. It is therefore crucial to prevent such incidents by denying protected branch deletion.", "ImpactStatement": "Protected branches cannot be deleted.", - "RemediationProcedure": "For each repository that is being used, block the option to delete protected branches by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n 5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n 6. Uncheck **Allow deletions**.\n 7. Click **Create** or **Save changes**.", - "AuditProcedure": "For each repository that is being used, verify that protected branches cannot be deleted by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n 5. Ensure that **Allow deletions** is not checked.", + "RemediationProcedure": "For each repository that is being used, block the option to delete protected branches by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, click **Add rule**.\n5. If you add the rule, under \"Branch name pattern\", type the branch name or pattern you want to protect.\n6. Uncheck **Allow deletions**.\n7. Click **Create** or **Save changes**.", + "AuditProcedure": "For each repository that is being used, verify that protected branches cannot be deleted by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", verify that there is at least one rule for your main branch. If there is, click **Edit** to its right. If there isn't, you are not compliant.\n5. Ensure that **Allow deletions** is not checked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule" + "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule", + "DefaultValue": "" } ] }, { "Id": "1.1.18", - "Description": "Ensure any merging of code is automatically scanned for risks", + "Description": "Ensure that every pull request is required to be scanned for risks.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure that every pull request is required to be scanned for risks.", "RationaleStatement": "Scanning pull requests to detect risks allows for early detection of vulnerable code and/or dependencies and helps mitigate potentially malicious code.", "ImpactStatement": "", - "RemediationProcedure": "For every repository in use, enforce risk scanning on every pull request by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Actions**.\n 3. If the repository already has at least one workflow set up and running, click **New workflow** and go to step 5. If there are currently no workflows configured for the repository, go to the next step.\n 4. Scroll down to the \"Security\" category and click **Configure** under the workflow you want to configure or click **View all** to see all available security workflows.\n 5. On the right pane of the workflow page, click **Documentation** and follow the on-screen instructions to tailor the workflow to your needs.", - "AuditProcedure": "For each repository in use, ensure that every pull request must be scanned for risks by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Actions**.\n 3. Ensure that at least one workflow is configured to run like that: \n ```\n on:\n push:\n branches: [ \"main\" ]\n pull_request:\n branches: [ \"main\" ]\n ```\n and that it has a step that runs code scanning on the code.", + "RemediationProcedure": "For every repository in use, enforce risk scanning on every pull request by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Actions**.\n3. If the repository already has at least one workflow set up and running, click **New workflow** and go to step 5. If there are currently no workflows configured for the repository, go to the next step.\n4. Scroll down to the \"Security\" category and click **Configure** under the workflow you want to configure or click **View all** to see all available security workflows.\n5. On the right pane of the workflow page, click **Documentation** and follow the on-screen instructions to tailor the workflow to your needs.", + "AuditProcedure": "For each repository in use, ensure that every pull request must be scanned for risks by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Actions**.\n3. Ensure that at least one workflow is configured to run like that: \n```\non:\n push:\n branches: [ \"main\" ]\n pull_request:\n branches: [ \"main\" ]\n```\nand that it has a step that runs code scanning on the code.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.1.19", - "Description": "Ensure any changes to branch protection rules are audited", + "Description": "Ensure that changes in the branch protection rules are audited.", "Checks": [], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure that changes in the branch protection rules are audited.", "RationaleStatement": "Branch protection rules should be configured on every repository. The only users who may change such rules are administrators. In a case of an attack on an administrator account or of human error on the part of an administrator, protection rules could be disabled, and thus decrease source code confidentiality as a result. It is important to track and audit such changes to prevent potential incidents as soon as possible.", "ImpactStatement": "", - "RemediationProcedure": "Use the audit log to audit changes in branch protection rules by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n 4. Use the action qualifier in your query and look for **protected_branch** category. Ensure every action is reasonable and secure and investigate if not.", - "AuditProcedure": "Ensure changes in branch protection rules are audited by performing the following regularly:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n 4. Use the action qualifier in your query and look for **protected_branch** category. Ensure every action is reasonable and secure and is investigated if not.", + "RemediationProcedure": "Use the audit log to audit changes in branch protection rules by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n4. Use the action qualifier in your query and look for **protected_branch** category. Ensure every action is reasonable and secure and investigate if not.", + "AuditProcedure": "Ensure changes in branch protection rules are audited by performing the following regularly:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n4. Use the action qualifier in your query and look for **protected_branch** category. Ensure every action is reasonable and secure and is investigated if not.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches" + "References": "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches", + "DefaultValue": "" } ] }, { "Id": "1.1.20", - "Description": "Ensure branch protection is enforced on the default branch", + "Description": "Enforce branch protection on the default and main branch.", "Checks": [ "repository_default_branch_protection_enabled" ], "Attributes": [ { - "Section": "1.1", + "Section": "1 Source Code", + "Subsection": "1.1 Code Changes", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Enforce branch protection on the default and main branch.", "RationaleStatement": "The default or main branch of repositories is considered very important, as it is eventually gets deployed to the production. Therefore it needs protection. By enforcing branch protection rules on this branch, it is secured from unwanted or unauthorized changes. It can also be protected from untested and unreviewed changes and more.", "ImpactStatement": "", - "RemediationProcedure": "Perform the following to enforce branch protection on the main branch:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Next to \"Branch protection rules\", click **Add rule**.\n 5. Under \"Branch name pattern\", type the branch name or pattern you want to protect. Ensure it applies to the main branch name.\n 6. Configure policies you want.\n 7. Click Create.", - "AuditProcedure": "Perform the following to ensure branch protection is enforced on the main branch:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n 4. Under **Branch protection rules**, verify that there is a rule applied to the \"main\" or default branch.", + "RemediationProcedure": "Perform the following to enforce branch protection on the main branch:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Next to \"Branch protection rules\", click **Add rule**.\n5. Under \"Branch name pattern\", type the branch name or pattern you want to protect. Ensure it applies to the main branch name.\n6. Configure policies you want.\n7. Click Create.", + "AuditProcedure": "Perform the following to ensure branch protection is enforced on the main branch:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Code and automation\" section of the sidebar, click **Branches**.\n4. Under **Branch protection rules**, verify that there is a rule applied to the \"main\" or default branch.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.2.1", - "Description": "Ensure all public repositories contain a SECURITY.md file", + "Description": "A SECURITY.md file is a security policy file that offers instruction on reporting security vulnerabilities in a project. When someone creates an issue within a specific project, a link to the SECURITY.md file will subsequently be shown.", "Checks": [ "repository_public_has_securitymd_file" ], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "A SECURITY.md file is a security policy file that offers instruction on reporting security vulnerabilities in a project. When someone creates an issue within a specific project, a link to the SECURITY.md file will subsequently be shown.", "RationaleStatement": "A SECURITY.md file provides users with crucial security information. It can also serve an important role in project maintenance, encouraging users to think ahead about how to properly handle potential security issues, updates, and general security practices.", "ImpactStatement": "", - "RemediationProcedure": "Enforce that each public repository has a SECURITY.md file by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under the repository name, click **Security**.\n 3. In the left sidebar, click **Security policy**.\n 4. Click **Start setup**.\n 5. In the new SECURITY.md file, add information about supported versions of your project and how to report a vulnerability.\n 6. At the bottom of the page, type a commit message.\n 7. Below the commit message fields, choose to create a new branch for your commit and then create a pull request.\n 8. Click **Propose file change**.", - "AuditProcedure": "Verify that each public repository has a SECURITY.md file by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under the repository name, click **Security**.\n 3. Verify that **Security policy** is enabled.", + "RemediationProcedure": "Enforce that each public repository has a SECURITY.md file by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under the repository name, click **Security**.\n3. In the left sidebar, click **Security policy**.\n4. Click **Start setup**.\n5. In the new SECURITY.md file, add information about supported versions of your project and how to report a vulnerability.\n6. At the bottom of the page, type a commit message.\n7. Below the commit message fields, choose to create a new branch for your commit and then create a pull request.\n8. Click **Propose file change**.", + "AuditProcedure": "Verify that each public repository has a SECURITY.md file by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under the repository name, click **Security**.\n3. Verify that **Security policy** is enabled.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.2.2", - "Description": "Ensure repository creation is limited to specific members", + "Description": "Limit the ability to create repositories to trusted users and teams.", "Checks": [], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Limit the ability to create repositories to trusted users and teams.", "RationaleStatement": "Restricting repository creation to trusted users and teams is recommended in order to keep the organization properly structured, track fewer items, prevent impersonation, and to not overload the version-control system. It will allow administrators easier source code tracking and management capabilities, as they will have fewer repositories to track. The process of detecting potential attacks also becomes far more straightforward, as well, since the easier it is to track the source code, the easier it is to detect malicious acts within it. Additionally, the possibility of a member creating a public repository and sharing the organization's data externally is significantly decreased.", "ImpactStatement": "Specific users will not be permitted to create repositories.", - "RemediationProcedure": "Restrict repository creation to trusted users and teams only by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Member privileges**.\n 4. Under \"Repository creation\", unselect both options - **Public** and **Private**.\n 5. Click **Save**.", - "AuditProcedure": "Verify that only trusted users and teams can create repositories by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Member privileges**.\n 4. Under \"Repository creation\", ensure that **Public** and **Private** are not checked. This means only owners are able to create repositories.", + "RemediationProcedure": "Restrict repository creation to trusted users and teams only by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Member privileges**.\n4. Under \"Repository creation\", unselect both options - **Public** and **Private**.\n5. Click **Save**.", + "AuditProcedure": "Verify that only trusted users and teams can create repositories by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Member privileges**.\n4. Under \"Repository creation\", ensure that **Public** and **Private** are not checked. This means only owners are able to create repositories.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.2.3", - "Description": "Ensure repository deletion is limited to specific users", + "Description": "Ensure only a limited number of trusted users can delete repositories.", "Checks": [], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure only a limited number of trusted users can delete repositories.", "RationaleStatement": "Restricting the ability to delete repositories protects the organization from intentional and unintentional data loss. This ensures that users cannot delete repositories or cause other potential damage — whether by accident or due to their account being hacked — unless they have the correct privileges.", "ImpactStatement": "Certain users will not be permitted to delete repositories.", - "RemediationProcedure": "Enforce repository deletion by a few trusted and responsible users only by performing either of the following steps:\n \n\n If Your organizations > Settings > Access > Member privileges > Allow members to delete or transfer repositories for this organization is selected, allow only trusted members to have admin privileges:\n 1. In every repository, on GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n 3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Change their role by clicking the **Role** dropdown next to the username until there are only two trusted and qualified users with admin privileges. \n \n\n If it is not selected, allow only trusted users to become an organization owner:\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Click the name of your organization and under your organization name, click **People**.\n 3. You will see a list of the people in your organization. Click Role and select Owners. Check every member you want to change permissions to. Above the list of members, use the drop-down menu and click Change role and choose Member > change role. Do that until there are only a few trusted and qualified users with organization owner privileges. \n \n\n In any case, only members with administrator or organization owner privileges can delete repositories, regardless of your setting.", - "AuditProcedure": "Verify that only a limited number of trusted users can delete repositories by performing either of the following steps:\n \n\n If Your organizations > Settings > Access > Member privileges > Allow members to delete or transfer repositories for this organization is selected, verify that every admin member is trusted by you:\n 1. In every repository, on GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n 3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Verify that there are only two of them and that they are trusted and qualified. \n \n\n If it is not selected, verify that every organization owner is trusted by you:\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Click the name of your organization and under your organization name, click **People**.\n 3. You will see a list of the people in your organization. Click Role and select Owners. Verify that there are only a few of them and that they are trusted and qualified. \n \n\n In any case, only members with administrator or organization owner privileges can delete repositories, regardless of your setting.", + "RemediationProcedure": "Enforce repository deletion by a few trusted and responsible users only by performing either of the following steps:\n\nIf Your organizations > Settings > Access > Member privileges > Allow members to delete or transfer repositories for this organization is selected, allow only trusted members to have admin privileges:\n1. In every repository, on GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Change their role by clicking the **Role** dropdown next to the username until there are only two trusted and qualified users with admin privileges. \n\nIf it is not selected, allow only trusted users to become an organization owner:\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Click the name of your organization and under your organization name, click **People**.\n3. You will see a list of the people in your organization. Click Role and select Owners. Check every member you want to change permissions to. Above the list of members, use the drop-down menu and click Change role and choose Member > change role. Do that until there are only a few trusted and qualified users with organization owner privileges. \n\nIn any case, only members with administrator or organization owner privileges can delete repositories, regardless of your setting.", + "AuditProcedure": "Verify that only a limited number of trusted users can delete repositories by performing either of the following steps:\n\nIf Your organizations > Settings > Access > Member privileges > Allow members to delete or transfer repositories for this organization is selected, verify that every admin member is trusted by you:\n1. In every repository, on GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Verify that there are only two of them and that they are trusted and qualified. \n\nIf it is not selected, verify that every organization owner is trusted by you:\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Click the name of your organization and under your organization name, click **People**.\n3. You will see a list of the people in your organization. Click Role and select Owners. Verify that there are only a few of them and that they are trusted and qualified. \n\nIn any case, only members with administrator or organization owner privileges can delete repositories, regardless of your setting.", "AdditionalInformation": "", - "DefaultValue": "Only organization owners or members with admin privileges can delete repositories.", - "References": "" + "References": "", + "DefaultValue": "Only organization owners or members with admin privileges can delete repositories." } ] }, { "Id": "1.2.4", - "Description": "Ensure issue deletion is limited to specific users", + "Description": "Ensure only trusted and responsible users can delete issues.", "Checks": [], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure only trusted and responsible users can delete issues.", "RationaleStatement": "Issues are a way to keep track of things happening in repositories, such as setting new milestones or requesting urgent fixes. Deleting an issue is not a benign activity, as it might harm the development workflow or attempt to hide malicious behavior. Because of this, it should be restricted and allowed only by trusted and responsible users.", "ImpactStatement": "Certain users will not be permitted to delete issues.", - "RemediationProcedure": "Restrict issue deletion to a few trusted and responsible users only by performing either of the following steps:\n \n\n If Your organizations > Settings > Access > Member privileges > Allow members to delete issues for this organization is selected, allow only trusted members to have admin privileges:\n 1. In every repository, on GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n 3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Change their role by clicking the **Role** dropdown next to the username until there are only two trusted and qualified users with admin privileges.\n \n\n If it is not selected, allow only trusted users to become an organization owner:\n 1. In the top right corner of GitHub.com, click your profile photo, then click Your organizations.\n 2. Click the name of your organization and under your organization name, click **People**.\n 3. You will see a list of the people in your organization. Click **Role** and select **Owners**. Check every member you want to change permissions to. Above the list of members, use the drop-down menu and click **Change role** and choose Member > change role. Do that until there are only a few trusted and qualified users with organization owner privileges.\n \n\n In any case, only members with administrator or organization owner privileges can delete issues, regardless of your setting.", - "AuditProcedure": "Verify that only a limited number of trusted users can delete issues by performing either of the following steps:\n \n\n If Your organizations > Settings > Access > Member privileges > Allow members to delete issues for this organization is selected, verify that every admin member is trusted by you:\n 1. In every repository, on GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n 3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Verify that there are only two of them and that they are trusted and qualified.\n \n\n If it is not selected, verify that every organization owner is trusted by you:\n 1. In the top right corner of GitHub.com, click your profile photo, then click Your organizations.\n 2. Click the name of your organization and under your organization name, click **People**.\n 3. You will see a list of the people in your organization. Click **Role** and select **Owners**. Verify that there are only a few of them and that they are trusted and qualified.\n \n\n In any case, only members with administrator or organization owner privileges can delete issues, regardless of your setting.", + "RemediationProcedure": "Restrict issue deletion to a few trusted and responsible users only by performing either of the following steps:\n\nIf Your organizations > Settings > Access > Member privileges > Allow members to delete issues for this organization is selected, allow only trusted members to have admin privileges:\n1. In every repository, on GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Change their role by clicking the **Role** dropdown next to the username until there are only two trusted and qualified users with admin privileges.\n\nIf it is not selected, allow only trusted users to become an organization owner:\n1. In the top right corner of GitHub.com, click your profile photo, then click Your organizations.\n2. Click the name of your organization and under your organization name, click **People**.\n3. You will see a list of the people in your organization. Click **Role** and select **Owners**. Check every member you want to change permissions to. Above the list of members, use the drop-down menu and click **Change role** and choose Member > change role. Do that until there are only a few trusted and qualified users with organization owner privileges.\n\nIn any case, only members with administrator or organization owner privileges can delete issues, regardless of your setting.", + "AuditProcedure": "Verify that only a limited number of trusted users can delete issues by performing either of the following steps:\n\nIf Your organizations > Settings > Access > Member privileges > Allow members to delete issues for this organization is selected, verify that every admin member is trusted by you:\n1. In every repository, on GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings** and then in the \"Access\" section of the sidebar, click **Collaborators & teams**.\n3. Under \"Manage access\" use the dropdown **Role** menu to filter and search for admin members. Verify that there are only two of them and that they are trusted and qualified.\n\nIf it is not selected, verify that every organization owner is trusted by you:\n1. In the top right corner of GitHub.com, click your profile photo, then click Your organizations.\n2. Click the name of your organization and under your organization name, click **People**.\n3. You will see a list of the people in your organization. Click **Role** and select **Owners**. Verify that there are only a few of them and that they are trusted and qualified.\n\nIn any case, only members with administrator or organization owner privileges can delete issues, regardless of your setting.", "AdditionalInformation": "", - "DefaultValue": "Only organization owners or members with admin privileges can delete issues.", - "References": "" + "References": "", + "DefaultValue": "Only organization owners or members with admin privileges can delete issues." } ] }, { "Id": "1.2.5", - "Description": "Ensure all copies (forks) of code are tracked and accounted for", + "Description": "Track every fork of code and ensure it is accounted for.", "Checks": [], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Track every fork of code and ensure it is accounted for.", "RationaleStatement": "A fork is a copy of a repository. On top of being a plain copy, any updates to the original repository itself can be pulled and reflected by the fork under certain conditions. A large number of repository copies (forks) become difficult to manage and properly secure. New and sensitive changes can often be pushed into a critical repository without developer knowledge of an updated copy of the very same repository. If there is no limit on doing this, then it is recommended to track and delete copies of organization repositories as needed.", "ImpactStatement": "Disabling forks completely may slow down the development process as more actions will be necessary to take in order to fork a repository.", - "RemediationProcedure": "Track forks and examine them by performing the following on a regular basis:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Insights**.\n 3. In the left sidebar, click **Forks**.\n 4. Examine the forks listed there.", - "AuditProcedure": "Verify that the following steps are done regularly to track and examine forks:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Insights**.\n 3. In the left sidebar, click **Forks**.\n 4. Examine the forks listed there.", + "RemediationProcedure": "Track forks and examine them by performing the following on a regular basis:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Insights**.\n3. In the left sidebar, click **Forks**.\n4. Examine the forks listed there.", + "AuditProcedure": "Verify that the following steps are done regularly to track and examine forks:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Insights**.\n3. In the left sidebar, click **Forks**.\n4. Examine the forks listed there.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.2.6", - "Description": "Ensure all code projects are tracked for changes in visibility status", + "Description": "Ensure every change in visibility of projects is tracked.", "Checks": [], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure every change in visibility of projects is tracked.", "RationaleStatement": "Visibility of projects determines who can access a project and/or fork it: anyone, designated users, or only members of the organization. If a private project becomes public, this may point to a potential attack, which can ultimately lead to data loss, the leaking of sensitive information, and finally to a supply chain attack. It is crucial to track these changes in order to prevent such incidents.", "ImpactStatement": "", - "RemediationProcedure": "Track every change in project visibility and investigate if suspicious behavior occurs, by performing the following regularly:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n 4. Use the **repo** qualifier in your query and look for **access** category. Ensure every change is reasonable and secure and investigate if it is not.", - "AuditProcedure": "Ensure that every change in project visibility is tracked and investigated, by performing the following regularly:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n 4. Use the **repo** qualifier in your query and look for **access** category. Ensure every change is reasonable and secure and is investigated if it is not.", + "RemediationProcedure": "Track every change in project visibility and investigate if suspicious behavior occurs, by performing the following regularly:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n4. Use the **repo** qualifier in your query and look for **access** category. Ensure every change is reasonable and secure and investigate if it is not.", + "AuditProcedure": "Ensure that every change in project visibility is tracked and investigated, by performing the following regularly:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Archives\" section of the sidebar, click **Logs**, then click **Audit log**.\n4. Use the **repo** qualifier in your query and look for **access** category. Ensure every change is reasonable and secure and is investigated if it is not.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.2.7", - "Description": "Ensure inactive repositories are reviewed and archived periodically", + "Description": "Track inactive repositories and remove them periodically.", "Checks": [], "Attributes": [ { - "Section": "1.2", + "Section": "1 Source Code", + "Subsection": "1.2 Repository Management", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Track inactive repositories and remove them periodically.", "RationaleStatement": "Inactive repositories (i.e., no new changes introduced for a long period of time) can enlarge the surface of a potential attack or data leak. These repositories are more likely to be improperly managed, and thus could possibly be accessed by a large number of users in an organization.", "ImpactStatement": "Bug fixes and deployment of necessary changes could prove complicated for archived repositories.", - "RemediationProcedure": "Perform the following to review all inactive repositories and archive them periodically:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Click on your organization name and then on **repositories**.\n 3. Ensure every repository listed has been active in the last 3 to 6 months. Every repository that isn't active you should either review or archive by performing the next steps:\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. Under \"Danger Zone\", click **Archive this repository**.\n 4. Read the warnings.\n 5. Type the name of the repository you want to archive.\n 6. Click **I understand the consequences, archive this repository**.", - "AuditProcedure": "Perform the following to ensure that all the repositories in the organization are active, and those that are not reviewed or archived:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Click on your organization name and then on **repositories**.\n 3. Ensure every repository listed has been active in the last 3 to 6 months. If it's not, then ensure it is archived or reviewed regularly.", + "RemediationProcedure": "Perform the following to review all inactive repositories and archive them periodically:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Click on your organization name and then on **repositories**.\n3. Ensure every repository listed has been active in the last 3 to 6 months. Every repository that isn't active you should either review or archive by performing the next steps:\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. Under \"Danger Zone\", click **Archive this repository**.\n 4. Read the warnings.\n 5. Type the name of the repository you want to archive.\n 6. Click **I understand the consequences, archive this repository**.", + "AuditProcedure": "Perform the following to ensure that all the repositories in the organization are active, and those that are not reviewed or archived:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Click on your organization name and then on **repositories**.\n3. Ensure every repository listed has been active in the last 3 to 6 months. If it's not, then ensure it is archived or reviewed regularly.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.1", - "Description": "Ensure inactive users are reviewed and removed periodically", + "Description": "Track inactive user accounts and periodically remove them.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Track inactive user accounts and periodically remove them.", "RationaleStatement": "User accounts that have been inactive for a long period of time are enlarging the surface of attack. Inactive users with high-level privileges are of particular concern, as these accounts are more likely to be targets for attackers. This could potentially allow access to large portions of an organization should such an attack prove successful. It is recommended to remove them as soon as possible in order to prevent this.", "ImpactStatement": "", - "RemediationProcedure": "If you have GitHub AE, perform the following to review inactive user accounts and remove them:\n \n\n 1. From an administrative account on GitHub AE, in the upper-right corner of any page, click the rocket icon.\n 2. If you're not already on the \"Site admin\" page, in the upper-left corner, click **Site admin**.\n 3. In the left sidebar, click **Dormant users**.\n 4. Find the users listed there under **Your organizations** > your organization > **People** and select them.\n 5. Click **Remove from organization** and **Remove members**.\n \n\n If you have GitHub Enterprise Cloud, perform the following:\n \n\n 1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n 2. In the list of enterprises, click the enterprise you want to view.\n 3. In the enterprise account sidebar, click **Compliance**.\n 4. To download your Dormant Users (beta) report as a CSV file, under \"Other\", click **Download**.\n 5. Find the users listed in the file under **Your organizations** > your organization > **People** and select them.\n 6. Click **Remove from organization** and **Remove members**.", - "AuditProcedure": "If you have GitHub AE, verify that all user accounts are active by performing the following:\n \n\n 1. From an administrative account on GitHub AE, in the upper-right corner of any page, click the rocket icon.\n 2. If you're not already on the \"Site admin\" page, in the upper-left corner, click **Site admin**.\n 3. In the left sidebar, click **Dormant users**.\n 4. Verify that the list is empty.\n \n\n If you have GitHub Enterprise Cloud, perform the following:\n \n\n 1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n 2. In the list of enterprises, click the enterprise you want to view.\n 3. In the enterprise account sidebar, click **Compliance**.\n 4. To download your Dormant Users (beta) report as a CSV file, under \"Other\", click **Download**.\n 5. Verify that there are no users listed.", + "RemediationProcedure": "If you have GitHub AE, perform the following to review inactive user accounts and remove them:\n\n1. From an administrative account on GitHub AE, in the upper-right corner of any page, click the rocket icon.\n2. If you're not already on the \"Site admin\" page, in the upper-left corner, click **Site admin**.\n3. In the left sidebar, click **Dormant users**.\n4. Find the users listed there under **Your organizations** > your organization > **People** and select them.\n5. Click **Remove from organization** and **Remove members**.\n\nIf you have GitHub Enterprise Cloud, perform the following:\n\n1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n2. In the list of enterprises, click the enterprise you want to view.\n3. In the enterprise account sidebar, click **Compliance**.\n4. To download your Dormant Users (beta) report as a CSV file, under \"Other\", click **Download**.\n5. Find the users listed in the file under **Your organizations** > your organization > **People** and select them.\n6. Click **Remove from organization** and **Remove members**.", + "AuditProcedure": "If you have GitHub AE, verify that all user accounts are active by performing the following:\n\n1. From an administrative account on GitHub AE, in the upper-right corner of any page, click the rocket icon.\n2. If you're not already on the \"Site admin\" page, in the upper-left corner, click **Site admin**.\n3. In the left sidebar, click **Dormant users**.\n4. Verify that the list is empty.\n\nIf you have GitHub Enterprise Cloud, perform the following:\n\n1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n2. In the list of enterprises, click the enterprise you want to view.\n3. In the enterprise account sidebar, click **Compliance**.\n4. To download your Dormant Users (beta) report as a CSV file, under \"Other\", click **Download**.\n5. Verify that there are no users listed.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.2", - "Description": "Ensure team creation is limited to specific members", + "Description": "Limit ability to create teams to trusted and specific users.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Limit ability to create teams to trusted and specific users.", "RationaleStatement": "The ability to create new teams should be restricted to specific members in order to keep the organization orderly and ensure users have access to only the lowest privilege level necessary. Teams typically inherit permissions from their parent team, thus if base permissions are less restricted and any user has the ability to create a team, a permission leverage could occur in which certain data is made available to users who should not have access to it. Such a situation could potentially lead to the creation of shadow teams by an attacker. Restricting team creation will also reduce additional clutter in the organizational structure, and as a result will make it easier to track changes and anomalies.", "ImpactStatement": "Only specific users will be able to create new teams.", - "RemediationProcedure": "For every organization, limit team creation to specific, trusted users by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Member privileges**.\n 4. Under \"Team creation rules\", deselect **Allow members to create teams**.\n 5. Click **Save**.", - "AuditProcedure": "For every organization, ensure that team creation is limited to specific, trusted users by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Member privileges**.\n 4. Under \"Team creation rules\", verify that **Allow members to create teams** is not selected.", + "RemediationProcedure": "For every organization, limit team creation to specific, trusted users by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Member privileges**.\n4. Under \"Team creation rules\", deselect **Allow members to create teams**.\n5. Click **Save**.", + "AuditProcedure": "For every organization, ensure that team creation is limited to specific, trusted users by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Member privileges**.\n4. Under \"Team creation rules\", verify that **Allow members to create teams** is not selected.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.3", - "Description": "Ensure minimum number of administrators are set for the organization", + "Description": "Ensure the organization has a minimum number of administrators.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure the organization has a minimum number of administrators.", "RationaleStatement": "Organization administrators have the highest level of permissions, including the ability to add/remove collaborators, create or delete repositories, change branch protection policy, and convert to a publicly-accessible repository. Due to the permissive access granted to an organization administrator, it is highly recommended to keep the number of administrator accounts as minimal as possible.", "ImpactStatement": "", - "RemediationProcedure": "Set the minimum number of administrators in your organization by performing the following:\n \n\n 1. In the top right corner of GitHub, click your profile photo, then click **Your profile**.\n 2. On the left side of your profile page, under \"Organizations\", click the icon for your organization.\n 3. Under your organization name, click **People**. \n 4. In the Role drop-down, choose **Owners**.\n 5. Select the person or people you'd like to remove from owner role.\n 6. Above the list of members, use the drop-down menu and click Change role.\n 7. Select **Member**, then click **Change role**.", - "AuditProcedure": "Verify the minimum number of administrators in your organization by performing the following:\n \n\n 1. In the top right corner of GitHub, click your profile photo, then click **Your profile**.\n 2. On the left side of your profile page, under \"Organizations\", click the icon for your organization.\n 3. Under your organization name, click **People**. \n 4. In the Role drop-down, choose **Owners**.\n 5. If there are minimum number of members in the list, you are compliant.", + "RemediationProcedure": "Set the minimum number of administrators in your organization by performing the following:\n\n1. In the top right corner of GitHub, click your profile photo, then click **Your profile**.\n2. On the left side of your profile page, under \"Organizations\", click the icon for your organization.\n3. Under your organization name, click **People**. \n4. In the Role drop-down, choose **Owners**.\n5. Select the person or people you'd like to remove from owner role.\n6. Above the list of members, use the drop-down menu and click Change role.\n7. Select **Member**, then click **Change role**.", + "AuditProcedure": "Verify the minimum number of administrators in your organization by performing the following:\n\n1. In the top right corner of GitHub, click your profile photo, then click **Your profile**.\n2. On the left side of your profile page, under \"Organizations\", click the icon for your organization.\n3. Under your organization name, click **People**. \n4. In the Role drop-down, choose **Owners**.\n5. If there are minimum number of members in the list, you are compliant.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.4", - "Description": "Ensure Multi-Factor Authentication (MFA) is required for contributors of new code", + "Description": "Require collaborators from outside the organization to use Multi-Factor Authentication (MFA) in addition to a standard user name and password when authenticating to the source code management platform.", "Checks": [ "organization_members_mfa_required" ], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Require collaborators from outside the organization to use Multi-Factor Authentication (MFA) in addition to a standard user name and password when authenticating to the source code management platform.", "RationaleStatement": "By default every user authenticates within the system by password only. If the password of a user is compromised, however, the user account and every repository to which they have access are in danger of data loss, malicious code commits, and data theft. It is therefore recommended that each user has Multi-Factor Authentication enabled. This adds an additional layer of protection to ensure the account remains secure even if the user's password is compromised.", "ImpactStatement": "A member without enabled Multi-Factor Authentication cannot contribute to the project. They must enable Multi-Factor Authentication a before they can contribute any code.", - "RemediationProcedure": "For each repository in use, enforce Multi-Factor Authentication is the only way to authenticate for contributors, by doing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. Under \"Authentication\", select **Require two-factor authentication for everyone in your organization**, then click **Save**.", - "AuditProcedure": "For each repository in use, verify that Multi-Factor Authentication is enforced for contributors and is the only way to authenticate, by doing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. Under \"Authentication\", check if **Require two-factor authentication for everyone in your organization** is checked. If so, you are compliant.", + "RemediationProcedure": "For each repository in use, enforce Multi-Factor Authentication is the only way to authenticate for contributors, by doing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. Under \"Authentication\", select **Require two-factor authentication for everyone in your organization**, then click **Save**.", + "AuditProcedure": "For each repository in use, verify that Multi-Factor Authentication is enforced for contributors and is the only way to authenticate, by doing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. Under \"Authentication\", check if **Require two-factor authentication for everyone in your organization** is checked. If so, you are compliant.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.5", - "Description": "Ensure the organization is requiring members to use Multi-Factor Authentication (MFA)", + "Description": "Require members of the organization to use Multi-Factor Authentication (MFA) in addition to a standard user name and password when authenticating to the source code management platform.", "Checks": [ "organization_members_mfa_required" ], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Require members of the organization to use Multi-Factor Authentication (MFA) in addition to a standard user name and password when authenticating to the source code management platform.", "RationaleStatement": "By default every user authenticates within the system by password only. If the password of a user is compromised, however, the user account and every repository to which they have access are in danger of data loss, malicious code commits, and data theft. It is therefore recommended that each user has Multi-Factor Authentication enabled. This adds an additional layer of protection to ensure the account remains secure even if the user's password is compromised.", "ImpactStatement": "Members will be removed from the organization if they don't have Multi-Factor Authentication already enabled. If this is the case, it is recommended that an invitation be sent to reinstate the user's access and former privileges. They must enable Multi-Factor Authentication to accept the invitation.", - "RemediationProcedure": "For every organization that exists in your GitHub platform, enforce Multi-Factor Authentication and define it as the only way to authenticate, by doing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. Under \"Authentication\", select **Require two-factor authentication for everyone in your organization**, then click **Save**.\n 5. If prompted, read the information about members and outside collaborators who will be removed from the organization. Type your organization's name to confirm the change, then click **Remove members & require two-factor authentication**.", - "AuditProcedure": "For every organization that exists in your GitHub platform, verify that Multi-Factor Authentication is enforced and is the only way to authenticate, by doing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. Under \"Authentication\", check if **Require two-factor authentication for everyone in your organization** is checked. If so, you are compliant.", + "RemediationProcedure": "For every organization that exists in your GitHub platform, enforce Multi-Factor Authentication and define it as the only way to authenticate, by doing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. Under \"Authentication\", select **Require two-factor authentication for everyone in your organization**, then click **Save**.\n5. If prompted, read the information about members and outside collaborators who will be removed from the organization. Type your organization's name to confirm the change, then click **Remove members & require two-factor authentication**.", + "AuditProcedure": "For every organization that exists in your GitHub platform, verify that Multi-Factor Authentication is enforced and is the only way to authenticate, by doing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. Under \"Authentication\", check if **Require two-factor authentication for everyone in your organization** is checked. If so, you are compliant.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.6", - "Description": "Ensure new members are required to be invited using company-approved email", + "Description": "Existing members of an organization can invite new members to join, however new members must only be invited with their company-approved email.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Existing members of an organization can invite new members to join, however new members must only be invited with their company-approved email.", "RationaleStatement": "Ensuring new members of an organization have company-approved email prevents existing members of the organization from inviting arbitrary new users to join. Without this verification, they can invite anyone who is using the organization's version control system or has an active email account, thus allowing outside users (and potential threat actors) to easily gain access to company private code and resources. This practice will subsequently reduce the chance of human error or typos when inviting a new member.", "ImpactStatement": "Existing members would not be able to invite new users who do not have a company-approved email address.", - "RemediationProcedure": "For each organization, allow only users with company-approved email to be invited. If a user was invited without company-approved email, perform the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Click the name of your organization and under your organization name, click **People**.\n 3. On the People tab, click **Invitations**. Next to the username or email address of the person whose invitation you'd like to cancel, click **Edit invitation**.\n 4. To cancel the user's invitation to join your organization, click **Cancel invitation**.", - "AuditProcedure": "For each organization in use, verify for every invitation that the invited email address is company-approved by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Click the name of your organization and under your organization name, click **People**.\n 3. On the People tab, click **Invitations**. Verify that each invitation email is company approved by your company.", + "RemediationProcedure": "For each organization, allow only users with company-approved email to be invited. If a user was invited without company-approved email, perform the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Click the name of your organization and under your organization name, click **People**.\n3. On the People tab, click **Invitations**. Next to the username or email address of the person whose invitation you'd like to cancel, click **Edit invitation**.\n4. To cancel the user's invitation to join your organization, click **Cancel invitation**.", + "AuditProcedure": "For each organization in use, verify for every invitation that the invited email address is company-approved by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Click the name of your organization and under your organization name, click **People**.\n3. On the People tab, click **Invitations**. Verify that each invitation email is company approved by your company.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.7", - "Description": "Ensure two administrators are set for each repository", + "Description": "Ensure every repository has two users with administrative permissions.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Ensure every repository has two users with administrative permissions.", "RationaleStatement": "Repository administrators have the highest permissions to said repository. These include the ability to add/remove collaborators, change branch protection policy, and convert to a publicly-accessible repository. Due to the liberal access granted to a repository administrator, it is highly recommended that only two contributors occupy this role.", "ImpactStatement": "Removing administrative users from a repository would result in them losing high-level access to that repository.", - "RemediationProcedure": "For every repository in use, set two administrators by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Collaborators & teams**.\n 4. Under **Manage access**, find the team or person whose you'd like to revoke admin permissions, then select the Role drop-down and click a new role.", - "AuditProcedure": "For every repository in use, verify there are two administrators by performing the following:\n \n\n 1. On GitHub, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Collaborators & teams**.\n 4. Under **Manage access**, verify that there are only 2 members with Admin permission.", + "RemediationProcedure": "For every repository in use, set two administrators by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Collaborators & teams**.\n4. Under **Manage access**, find the team or person whose you'd like to revoke admin permissions, then select the Role drop-down and click a new role.", + "AuditProcedure": "For every repository in use, verify there are two administrators by performing the following:\n\n1. On GitHub, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Collaborators & teams**.\n4. Under **Manage access**, verify that there are only 2 members with Admin permission.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.8", - "Description": "Ensure strict base permissions are set for repositories", + "Description": "Base permissions define the permission level automatically granted to all organization members. Define strict base access permissions for all of the repositories in the organization, including new ones.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Base permissions define the permission level automatically granted to all organization members. Define strict base access permissions for all of the repositories in the organization, including new ones.", "RationaleStatement": "Defining strict base permissions is the best practice in every role-based access control (RBAC) system. If the base permission is high — for example, \"write\" permission — every member of the organization will have \"write\" permission to every repository in the organization. This will apply regardless of the specific permissions a user might need, which generally differ between organization repositories. The higher the permission, the higher the risk for incidents such as bad code commit or data breach. It is therefore recommended to set the base permissions to the strictest level possible.", "ImpactStatement": "Users might not be able to access organization repositories or perform some acts as commits. These specific permissions should be granted individually for each user or team, as needed.", - "RemediationProcedure": "Set strict base permissions for the organization repositories with the next steps:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Member privileges**.\n 4. Under \"Base permissions\", use the drop-down to select new base permissions - \"Read\" or \"None\".\n 5. Review the changes. To confirm, click **Change default permission to PERMISSION**.", - "AuditProcedure": "Verify that strict base permissions are set for the organization repositories by doing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Access\" section of the sidebar, click **Member privileges**.\n 4. Under \"Base permissions\", verify that it is set to \"Read\" or \"None\". If it does, you are compliant.", + "RemediationProcedure": "Set strict base permissions for the organization repositories with the next steps:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Member privileges**.\n4. Under \"Base permissions\", use the drop-down to select new base permissions - \"Read\" or \"None\".\n5. Review the changes. To confirm, click **Change default permission to PERMISSION**.", + "AuditProcedure": "Verify that strict base permissions are set for the organization repositories by doing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Access\" section of the sidebar, click **Member privileges**.\n4. Under \"Base permissions\", verify that it is set to \"Read\" or \"None\". If it does, you are compliant.", "AdditionalInformation": "", - "DefaultValue": "Read permission", - "References": "" + "References": "", + "DefaultValue": "Read permission" } ] }, { "Id": "1.3.9", - "Description": "Ensure an organization’s identity is confirmed with a “Verified” badge", + "Description": "Confirm the domains an organization owns with a \"Verified\" badge.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Confirm the domains an organization owns with a \"Verified\" badge.", "RationaleStatement": "Verifying the organization's domain gives developers assurance that a given domain is truly the official home for a public organization. Attackers can pretend to be an organization and steal information via a faked/spoof domain, therefore the use of a \"Verified\" badge instills more confidence and trust between developers and the open-source community.", "ImpactStatement": "", - "RemediationProcedure": "Only if you have an enterprise account, verify the organization's domains and secure a \"Verified\" badge next to its name by performing the following:\n \n\n 1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n 2. In the list of enterprises, click the enterprise you want to view. Then in the enterprise account sidebar, click **Settings**.\n 3. Under \"Settings\", click **Verified & approved domains**.\n 4. Click **Add a domain**.\n 5. In the domain field, type the domain you'd like to verify, then click **Add domain**.\n 6. Follow the instructions under **Add a DNS TXT record** to create a DNS TXT record with your domain hosting service. Wait for your DNS configuration to change, which may take up to 72 hours. You can confirm your DNS configuration has changed by running the `dig` command on the command line, replacing ENTERPRISE-ACCOUNT with the name of your enterprise account, and example.com with the domain you'd like to verify. You should see your new TXT record listed in the command output.\n ```\n dig _github-challenge-ENTERPRISE-ACCOUNT.DOMAIN-NAME +nostats +nocomments +nocmd TXT\n ```\n 7. After confirming your TXT record is added to your DNS, follow steps one through three above to navigate to your enterprise account's approved and verified domains.\n 8. To the right of the domain that's pending verification, click the 3-dots, then click **Continue verifying**. Click **Verify**.\n 9. Optionally, after the \"Verified\" badge is visible on your organizations' profiles, delete the TXT entry from the DNS record at your domain hosting service.", + "RemediationProcedure": "Only if you have an enterprise account, verify the organization's domains and secure a \"Verified\" badge next to its name by performing the following:\n\n1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n2. In the list of enterprises, click the enterprise you want to view. Then in the enterprise account sidebar, click **Settings**.\n3. Under \"Settings\", click **Verified & approved domains**.\n4. Click **Add a domain**.\n5. In the domain field, type the domain you'd like to verify, then click **Add domain**.\n6. Follow the instructions under **Add a DNS TXT record** to create a DNS TXT record with your domain hosting service. Wait for your DNS configuration to change, which may take up to 72 hours. You can confirm your DNS configuration has changed by running the `dig` command on the command line, replacing ENTERPRISE-ACCOUNT with the name of your enterprise account, and example.com with the domain you'd like to verify. You should see your new TXT record listed in the command output.\n```\ndig _github-challenge-ENTERPRISE-ACCOUNT.DOMAIN-NAME +nostats +nocomments +nocmd TXT\n```\n7. After confirming your TXT record is added to your DNS, follow steps one through three above to navigate to your enterprise account's approved and verified domains.\n8. To the right of the domain that's pending verification, click the 3-dots, then click **Continue verifying**. Click **Verify**.\n9. Optionally, after the \"Verified\" badge is visible on your organizations' profiles, delete the TXT entry from the DNS record at your domain hosting service.", "AuditProcedure": "Only if you have an enterprise account, view the enterprise organization profile page and ensure it has a \"Verified\" badge in it.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/organizations/managing-organization-settings/verifying-or-approving-a-domain-for-your-organization" + "References": "https://docs.github.com/en/organizations/managing-organization-settings/verifying-or-approving-a-domain-for-your-organization", + "DefaultValue": "" } ] }, { "Id": "1.3.10", - "Description": "Ensure Source Code Management (SCM) email notifications are restricted to verified domains", + "Description": "Restrict the Source Code Management (SCM) organization's email notifications to approved domains only.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Restrict the Source Code Management (SCM) organization's email notifications to approved domains only.", "RationaleStatement": "Restricting Source Code Management email notifications to verified domains only prevents data leaks, as personal emails and custom domains are more prone to account takeover via DNS hijacking or password breach.", "ImpactStatement": "Only members with approved email would be able to receive Source Code Management notifications.", - "RemediationProcedure": "Only if you have an enterprise account, restrict Source Code Management email notifications to approved domains only by performing the following:\n \n\n 1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n 2. In the list of enterprises, click the enterprise you want to view. Then in the enterprise account sidebar, click **Settings**.\n 3. Under \"Settings\", click **Verified & approved domains**.\n 4. Under \"Notification preferences\", select **Restrict email notifications to only approved or verified domains**.\n 5. Click **Save**.", - "AuditProcedure": "Only if you have an enterprise account, ensure Source Code Management email notifications are restricted to approved domains only by performing the following:\n \n\n 1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n 2. In the list of enterprises, click the enterprise you want to view. Then in the enterprise account sidebar, click **Settings**.\n 3. Under \"Settings\", click **Verified & approved domains**.\n 4. Under \"Notification preferences\", verify that **Restrict email notifications to only approved or verified domains** is selected.", + "RemediationProcedure": "Only if you have an enterprise account, restrict Source Code Management email notifications to approved domains only by performing the following:\n\n1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n2. In the list of enterprises, click the enterprise you want to view. Then in the enterprise account sidebar, click **Settings**.\n3. Under \"Settings\", click **Verified & approved domains**.\n4. Under \"Notification preferences\", select **Restrict email notifications to only approved or verified domains**.\n5. Click **Save**.", + "AuditProcedure": "Only if you have an enterprise account, ensure Source Code Management email notifications are restricted to approved domains only by performing the following:\n\n1. In the top-right corner of GitHub.com, click your profile photo, then click **Your enterprises**.\n2. In the list of enterprises, click the enterprise you want to view. Then in the enterprise account sidebar, click **Settings**.\n3. Under \"Settings\", click **Verified & approved domains**.\n4. Under \"Notification preferences\", verify that **Restrict email notifications to only approved or verified domains** is selected.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.11", - "Description": "Ensure an organization provides SSH certificates", + "Description": "As an organization, become an SSH Certificate Authority and provide SSH keys for accessing repositories.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "As an organization, become an SSH Certificate Authority and provide SSH keys for accessing repositories.", - "RationaleStatement": "There are two ways for remotely working with Source Code Management: via HTTPS, which requires authentication by user/password, or via SSH, which requires the use of SSH keys. SSH authentication is better in terms of security; key creation and distribution, however, must be done in a secure manner. This can be accomplished by implementing SSH certificates, which are used to validate the server's identity. A developer will not be able to connect to a Git server if its key cannot be verified by the SSH Certificate Authority (CA) server.\n As an organization, one can verify the SSH certificate signature used to authenticate if a CA is defined and used. This ensures that only verified developers can access organization repositories, as their SSH key will be the only one signed by the CA certificate. This reduces the risk of misuse and malicious code commits.", + "RationaleStatement": "There are two ways for remotely working with Source Code Management: via HTTPS, which requires authentication by user/password, or via SSH, which requires the use of SSH keys. SSH authentication is better in terms of security; key creation and distribution, however, must be done in a secure manner. This can be accomplished by implementing SSH certificates, which are used to validate the server's identity. A developer will not be able to connect to a Git server if its key cannot be verified by the SSH Certificate Authority (CA) server.\nAs an organization, one can verify the SSH certificate signature used to authenticate if a CA is defined and used. This ensures that only verified developers can access organization repositories, as their SSH key will be the only one signed by the CA certificate. This reduces the risk of misuse and malicious code commits.", "ImpactStatement": "Members with unverified keys will not be able to clone organization repositories. Signing, certification, and verification might also slow down the development process.", - "RemediationProcedure": "Only if you have an enterprise account, deploy an SSH Certificate Authority server and configure it to provide an SSH certificate with which to sign keys by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. To the right of \"SSH Certificate Authorities\", click **New CA**.\n 5. Under \"Key,\" paste your public SSH key.\n 6. Click **Add CA**.\n 7. Click **Save**.", - "AuditProcedure": "Only if you have an enterprise account, verify that the enterprise organization has an SSH Certificate Authority server and provides an SSH certificate with which to sign keys by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. Verify that there's an SSH certificate authority listed there.", + "RemediationProcedure": "Only if you have an enterprise account, deploy an SSH Certificate Authority server and configure it to provide an SSH certificate with which to sign keys by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. To the right of \"SSH Certificate Authorities\", click **New CA**.\n5. Under \"Key,\" paste your public SSH key.\n6. Click **Add CA**.\n7. Click **Save**.", + "AuditProcedure": "Only if you have an enterprise account, verify that the enterprise organization has an SSH Certificate Authority server and provides an SSH certificate with which to sign keys by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. Verify that there's an SSH certificate authority listed there.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.3.12", - "Description": "Ensure Git access is limited based on IP addresses", + "Description": "Limit Git access based on IP addresses by having a allowlist of IP addresses from which connection is possible.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Limit Git access based on IP addresses by having a allowlist of IP addresses from which connection is possible.", "RationaleStatement": "Allowing access to Git repositories (source code) only from specific IP addresses adds yet another layer of restriction and reduces the risk of unauthorized connection to the organization's assets. This will prevent attackers from accessing Source Code Management (SCM), as they would first need to know the allowed IP addresses to gain access to them.", "ImpactStatement": "Only members with allowlisted IP addresses will be able to access the organization's Git repositories.", - "RemediationProcedure": "Only if you have an enterprise account, create an IP allowlist and forbid all other IPs from accessing the source code by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. At the bottom of the \"IP allow list\" section, enter an IP address, or a range of addresses in CIDR notation. Optionally, enter a description of the allowed IP address or range.\n 5. Click **Add**.\n 6. After that, under \"IP allow list\", select **Enable IP allow list**.\n 7. Click **Save**.", - "AuditProcedure": "Only if you have an enterprise account, in every organization of yours, ensure access is allowed only by IP allowlist, and that access is forbidden for all other IPs by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Authentication security**.\n 4. Verify that there's an IP address, or a range of addresses in CIDR notation listed. Also verify that **Enable IP allow list** is selected.", + "RemediationProcedure": "Only if you have an enterprise account, create an IP allowlist and forbid all other IPs from accessing the source code by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. At the bottom of the \"IP allow list\" section, enter an IP address, or a range of addresses in CIDR notation. Optionally, enter a description of the allowed IP address or range.\n5. Click **Add**.\n6. After that, under \"IP allow list\", select **Enable IP allow list**.\n7. Click **Save**.", + "AuditProcedure": "Only if you have an enterprise account, in every organization of yours, ensure access is allowed only by IP allowlist, and that access is forbidden for all other IPs by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Authentication security**.\n4. Verify that there's an IP address, or a range of addresses in CIDR notation listed. Also verify that **Enable IP allow list** is selected.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-allowed-ip-addresses-for-your-organization" + "References": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-allowed-ip-addresses-for-your-organization", + "DefaultValue": "" } ] }, { "Id": "1.3.13", - "Description": "Ensure anomalous code behavior is tracked", + "Description": "Track code anomalies.", "Checks": [], "Attributes": [ { - "Section": "1.3", + "Section": "1 Source Code", + "Subsection": "1.3 Contribution Access", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Track code anomalies.", - "RationaleStatement": "Carefully analyze any code anomalies within the organization. For example, a code anomaly could be a push made outside of working hours. Such a code push has a higher likelihood of being the result of an attack, as most if not all members of the organization would likely be outside the office. Another example is an activity that exceeds the average activity of a particular user.\n Tracking and auditing such behaviors creates additional layers of security and can aid in early detection of potential attacks.", + "RationaleStatement": "Carefully analyze any code anomalies within the organization. For example, a code anomaly could be a push made outside of working hours. Such a code push has a higher likelihood of being the result of an attack, as most if not all members of the organization would likely be outside the office. Another example is an activity that exceeds the average activity of a particular user.\nTracking and auditing such behaviors creates additional layers of security and can aid in early detection of potential attacks.", "ImpactStatement": "", "RemediationProcedure": "For every repository in use, track and investigate anomalous code behavior and activity.", "AuditProcedure": "For every repository in use, ensure code anomalies relevant to the organization are promptly investigated.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.4.1", - "Description": "Ensure administrator approval is required for every installed application", + "Description": "Ensure an administrator approval is required when installing applications.", "Checks": [], "Attributes": [ { - "Section": "1.4", + "Section": "1 Source Code", + "Subsection": "1.4 Third-Party", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure an administrator approval is required when installing applications.", "RationaleStatement": "Applications are typically automated integrations that improve the workflow of an organization. They are written by third-party developers, and therefore should be validated before using in case they're malicious or not trustable. Because administrators are expected to be the most qualified and trusted members of the organization, they should review the applications being installed and decide whether they are both trusted and necessary.", "ImpactStatement": "Applications will not be installed without administrator approval.", - "RemediationProcedure": "Require an administrator approval for every installed application:\n \n\n a. For GitHub Apps, you are compliant by default. That is because by default only organization owners and administrators can install them.\n \n\n b. For OAuth Apps, perform the following:\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Third-party Access\" section of the sidebar, click **OAuth application policy**.\n 4. Under \"Third-party application access policy\", click **Setup application access restrictions**.\n 5. After you review the information about third-party access restrictions, click **Restrict third-party application access**.", - "AuditProcedure": "Verify that applications are installed only after receiving administrator approval:\n \n\n a. For GitHub Apps, you are compliant by default. That is because by default only organization owners and administrators can install them.\n \n\n b. For OAuth Apps, perform the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Third-party Access\" section of the sidebar, click **OAuth application policy**.\n 4. Under \"Third-party application access policy\" verify that the policy status is **Access restricted**.", + "RemediationProcedure": "Require an administrator approval for every installed application:\n\na. For GitHub Apps, you are compliant by default. That is because by default only organization owners and administrators can install them.\n\nb. For OAuth Apps, perform the following:\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Third-party Access\" section of the sidebar, click **OAuth application policy**.\n4. Under \"Third-party application access policy\", click **Setup application access restrictions**.\n5. After you review the information about third-party access restrictions, click **Restrict third-party application access**.", + "AuditProcedure": "Verify that applications are installed only after receiving administrator approval:\n\na. For GitHub Apps, you are compliant by default. That is because by default only organization owners and administrators can install them.\n\nb. For OAuth Apps, perform the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Third-party Access\" section of the sidebar, click **OAuth application policy**.\n4. Under \"Third-party application access policy\" verify that the policy status is **Access restricted**.", "AdditionalInformation": "", - "DefaultValue": "Maintainers are organization owners.", - "References": "" + "References": "", + "DefaultValue": "Maintainers are organization owners." } ] }, { "Id": "1.4.2", - "Description": "Ensure stale applications are reviewed and inactive ones are removed", + "Description": "Ensure stale (inactive) applications are reviewed and removed if no longer in use.", "Checks": [], "Attributes": [ { - "Section": "1.4", + "Section": "1 Source Code", + "Subsection": "1.4 Third-Party", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure stale (inactive) applications are reviewed and removed if no longer in use.", @@ -870,80 +912,84 @@ "RemediationProcedure": "Review all stale applications and periodically remove them.", "AuditProcedure": "Verify that all the applications in the organization are actively used, and remove those that are no longer in use.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.4.3", - "Description": "Ensure the access granted to each installed application is limited to the least privilege needed", + "Description": "Ensure installed application permissions are limited to the lowest privilege level required.", "Checks": [], "Attributes": [ { - "Section": "1.4", + "Section": "1 Source Code", + "Subsection": "1.4 Third-Party", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure installed application permissions are limited to the lowest privilege level required.", "RationaleStatement": "Applications are typically automated integrations that can improve the workflow of an organization. They are written by third-party developers, and therefore should be reviewed carefully before use. It is recommended to use the \"least privilege\" principle, granting applications the lowest level of permissions required. This may prevent harm from a potentially malicious application with unnecessarily high-level permissions leaking data or modifying source code.", "ImpactStatement": "", - "RemediationProcedure": "Grant permissions to applications by the \"least privilege\" principle, meaning the lowest possible permission necessary:\n \n\n a. For GitHub Apps, perform the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Integrations\" section of the sidebar, click **GitHub Apps**.\n 4. Next to every GitHub App, click **Configure**.\n 5. Review the GitHub App's permissions and repository access. Edit the permissions granted to the least possible. For example, restrict the number of repositories the App can access.\n 6. Click **Save**.", - "AuditProcedure": "Verify that each installed application has the least privilege needed:\n \n\n a. For GitHub Apps, perform the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the \"Integrations\" section of the sidebar, click **GitHub Apps**.\n 4. Next to every GitHub App, click **Configure**.\n 5. Review the GitHub App's permissions and repository access. Verify that the App permissions are the least possible and that it can access only necessary repositories.", + "RemediationProcedure": "Grant permissions to applications by the \"least privilege\" principle, meaning the lowest possible permission necessary:\n\na. For GitHub Apps, perform the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Integrations\" section of the sidebar, click **GitHub Apps**.\n4. Next to every GitHub App, click **Configure**.\n5. Review the GitHub App's permissions and repository access. Edit the permissions granted to the least possible. For example, restrict the number of repositories the App can access.\n6. Click **Save**.", + "AuditProcedure": "Verify that each installed application has the least privilege needed:\n\na. For GitHub Apps, perform the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the \"Integrations\" section of the sidebar, click **GitHub Apps**.\n4. Next to every GitHub App, click **Configure**.\n5. Review the GitHub App's permissions and repository access. Verify that the App permissions are the least possible and that it can access only necessary repositories.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.4.4", - "Description": "Ensure only secured webhooks are used", + "Description": "Use only secured webhooks in the source code management platform.", "Checks": [], "Attributes": [ { - "Section": "1.4", + "Section": "1 Source Code", + "Subsection": "1.4 Third-Party", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Use only secured webhooks in the source code management platform.", "RationaleStatement": "A webhook is an event listener, attached to critical and sensitive parts of the software delivery process. It is triggered by a list of events (such as a new code being committed), and when triggered, the webhook sends out a notification with some payload to specific internet endpoints. Since the payload of the webhook contains sensitive organization data, it's important all webhooks are directed to an endpoint (URL) protected by SSL verification (HTTPS). This helps ensure that the data sent is delivered to securely without any man-in-the-middle, who could easily access and even alter the payload of the request.", - "ImpactStatement": "Perform the following to ensure all webhooks used are secured (HTTPS):\n \n\n 1. Navigate to your organization or repository and select **Settings**.\n 2. Select **Webhooks** on the side menu.\n 3. Verify that each webhook URL starts with 'https'.", - "RemediationProcedure": "Perform the following to secure all webhooks used(over HTTPS):\n \n\n 1. Navigate to your organization or repository and select **Settings**.\n 2. Select **Webhooks** on the side menu.\n 3. Find the webhooks that starts with 'http' and not 'https'.\n 4. Ensure the endpoint (URL) of the webhook listens to secured port (443) and uses certificate.\n 5. Click **Edit**.\n 6. Change the payload URL to https and ensure **Enable SSL verification** is checked.\n 7. Click **Update webhook**.", - "AuditProcedure": "Perform the following to secure all webhooks used(over HTTPS):\n \n\n 1. Navigate to your organization or repository and select **Settings**.\n 2. Select **Webhooks** on the side menu.\n 3. Ensure all webhooks starts with 'https'.", + "ImpactStatement": "Perform the following to ensure all webhooks used are secured (HTTPS):\n\n1. Navigate to your organization or repository and select **Settings**.\n2. Select **Webhooks** on the side menu.\n3. Verify that each webhook URL starts with 'https'.", + "RemediationProcedure": "Perform the following to secure all webhooks used(over HTTPS):\n\n1. Navigate to your organization or repository and select **Settings**.\n2. Select **Webhooks** on the side menu.\n3. Find the webhooks that starts with 'http' and not 'https'.\n4. Ensure the endpoint (URL) of the webhook listens to secured port (443) and uses certificate.\n5. Click **Edit**.\n6. Change the payload URL to https and ensure **Enable SSL verification** is checked.\n7. Click **Update webhook**.", + "AuditProcedure": "Perform the following to secure all webhooks used(over HTTPS):\n\n1. Navigate to your organization or repository and select **Settings**.\n2. Select **Webhooks** on the side menu.\n3. Ensure all webhooks starts with 'https'.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.5.1", - "Description": "Ensure scanners are in place to identify and prevent sensitive data in code", + "Description": "Detect and prevent sensitive data in code, such as confidential ID numbers, passwords, etc.", "Checks": [ "repository_secret_scanning_enabled" ], "Attributes": [ { - "Section": "1.5", + "Section": "1 Source Code", + "Subsection": "1.5 Code Risks", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect and prevent sensitive data in code, such as confidential ID numbers, passwords, etc.", "RationaleStatement": "Having sensitive data in the source code makes it easier for attackers to maliciously use such information. In order to avoid this, designate scanners to identify and prevent the existence of sensitive data in the code.", "ImpactStatement": "", - "RemediationProcedure": "For every repository in use, designate scanners to identify and prevent sensitive data in code by performing the following (enterprise only):\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n 4. Scroll down to the bottom of the page and click **Enable** for secret scanning.", - "AuditProcedure": "For every repository in use, verify that scanners are set to identify and prevent the existence of sensitive data in code by performing the following (enterprise only):\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n 4. Scroll down to the bottom of the page. If you see a **Disable** button, it means that secret scanning is already enabled for the repository.", + "RemediationProcedure": "For every repository in use, designate scanners to identify and prevent sensitive data in code by performing the following (enterprise only):\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n4. Scroll down to the bottom of the page and click **Enable** for secret scanning.", + "AuditProcedure": "For every repository in use, verify that scanners are set to identify and prevent the existence of sensitive data in code by performing the following (enterprise only):\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n4. Scroll down to the bottom of the page. If you see a **Disable** button, it means that secret scanning is already enabled for the repository.", "AdditionalInformation": "By January 2023, this feature is supposed to be open to all plans. Until then it is only for enterprise users.", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.5.2", - "Description": "Ensure scanners are in place to secure Continuous Integration (CI) pipeline instructions", + "Description": "Detect and prevent misconfigurations and insecure instructions in CI pipelines", "Checks": [], "Attributes": [ { - "Section": "1.5", + "Section": "1 Source Code", + "Subsection": "1.5 Code Risks", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect and prevent misconfigurations and insecure instructions in CI pipelines", @@ -952,18 +998,19 @@ "RemediationProcedure": "Set a CI instructions scanning tool to identify and prevent misconfigurations and insecure instructions and scans all CI pipelines.", "AuditProcedure": "Verify that a CI instructions scanning tool is set to identify and prevent misconfigurations and insecure instructions and that it scans all CI pipelines.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.5.3", - "Description": "Ensure scanners are in place to secure Infrastructure as Code (IaC) instructions", + "Description": "Detect and prevent misconfigurations or insecure instructions in Infrastructure as Code (IaC) files, such as Terraform files.", "Checks": [], "Attributes": [ { - "Section": "1.5", + "Section": "1 Source Code", + "Subsection": "1.5 Code Risks", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect and prevent misconfigurations or insecure instructions in Infrastructure as Code (IaC) files, such as Terraform files.", @@ -972,60 +1019,63 @@ "RemediationProcedure": "For every repository that holds IaC instructions files, set a scanning tool to identify and prevent misconfigurations and insecure instructions.", "AuditProcedure": "For every repository that holds IaC instructions files, verify that a scanning tool is set to identify and prevent misconfigurations and insecure instructions.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.5.4", - "Description": "Ensure scanners are in place for code vulnerabilities", + "Description": "Detect and prevent known open source vulnerabilities in the code.", "Checks": [], "Attributes": [ { - "Section": "1.5", + "Section": "1 Source Code", + "Subsection": "1.5 Code Risks", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect and prevent known open source vulnerabilities in the code.", "RationaleStatement": "Open source code blocks are used a lot in developed software. This has its own advantages, but it also has risks. Because the code is open for everyone, it means that attackers can publish or add malicious code to these open-source code blocks, or use their knowledge to find vulnerabilities in an existing code. Detecting and fixing such code vulnerabilities, by SCA (Software Composition Analysis) prevents insecure flaws from reaching production. It gives another opportunity for developers to secure the source code before it is deployed in production, where it is far more exposed and vulnerable to attacks.", "ImpactStatement": "", - "RemediationProcedure": "For every repository that is in use, set a scanning tool to identify and prevent code vulnerabilities by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under the repository name, click **Security**.\n 3. To the right of \"Code scanning alerts\", click **Set up code scanning**.\n 4. Under \"Get started with code scanning\", click Set up this workflow on a workflow of your choice.\n 5. To customize how code scanning scans your code, edit the workflow.\n 6. Use the **Start commit** drop-down and type a commit message.\n 7. Choose whether you'd like to commit directly to the default branch or create a new branch and start a pull request.\n 8. Click **Commit new file** or **Propose new file**.", - "AuditProcedure": "For every repository that is in use, verify that a scanning tool is set to identify and prevent code vulnerabilities by performing the following:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under the repository name, click **Security**.\n 3. Verify that \"Code scanning alerts\" is **Enabled** or that there is a workflow that scans your code.", + "RemediationProcedure": "For every repository that is in use, set a scanning tool to identify and prevent code vulnerabilities by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under the repository name, click **Security**.\n3. To the right of \"Code scanning alerts\", click **Set up code scanning**.\n4. Under \"Get started with code scanning\", click Set up this workflow on a workflow of your choice.\n5. To customize how code scanning scans your code, edit the workflow.\n6. Use the **Start commit** drop-down and type a commit message.\n7. Choose whether you'd like to commit directly to the default branch or create a new branch and start a pull request.\n8. Click **Commit new file** or **Propose new file**.", + "AuditProcedure": "For every repository that is in use, verify that a scanning tool is set to identify and prevent code vulnerabilities by performing the following:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under the repository name, click **Security**.\n3. Verify that \"Code scanning alerts\" is **Enabled** or that there is a workflow that scans your code.", "AdditionalInformation": "All public repositories in all plans can use code scanning in GitHub. In private repositories, only GitHub Enterprise can use code scanning.", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.5.5", - "Description": "Ensure scanners are in place for open-source vulnerabilities in used packages", + "Description": "Detect, prevent and monitor known open-source vulnerabilities in packages that are being used.", "Checks": [ "repository_dependency_scanning_enabled" ], "Attributes": [ { - "Section": "1.5", + "Section": "1 Source Code", + "Subsection": "1.5 Code Risks", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect, prevent and monitor known open-source vulnerabilities in packages that are being used.", "RationaleStatement": "Open-source vulnerabilities might exist before one starts to use a package, but they are also discovered over time. New attacks and vulnerabilities are announced every now and then. It is important to keep track of these and to monitor whether the dependencies used are affected by the recent vulnerability. Detecting and fixing those packages' vulnerabilities decreases the attack surface within deployed and running applications that use such packages. It prevents security flaws from reaching the production environment which could eventually lead to a security breach.", "ImpactStatement": "", - "RemediationProcedure": "Set scanners that will monitor, identify, and prevent open-source vulnerabilities in packages by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n 3. Under \"Code security and analysis\", to the right of Dependabot alerts, click **Disable all** or **Enable all**.\n 4. Check the **Enable by default for new repositories** option and then click **Enable Dependabot alerts**.\n \n\n It is also recommended to use another additional solution for package scanning because GitHub doesn't always recognize the vulnerabilities.", - "AuditProcedure": "Verify that scanners are set to monitor, identify, and prevent open-source vulnerabilities in packages by performing the following:\n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n 3. Verify that the Dependabot alerts is enabled and that **Enable by default for new repositories** is checked.\n \n\n It is also recommended to verify that you're using another additional solution for package scanning because GitHub doesn't always recognize the vulnerabilities.", + "RemediationProcedure": "Set scanners that will monitor, identify, and prevent open-source vulnerabilities in packages by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n3. Under \"Code security and analysis\", to the right of Dependabot alerts, click **Disable all** or **Enable all**.\n4. Check the **Enable by default for new repositories** option and then click **Enable Dependabot alerts**.\n\nIt is also recommended to use another additional solution for package scanning because GitHub doesn't always recognize the vulnerabilities.", + "AuditProcedure": "Verify that scanners are set to monitor, identify, and prevent open-source vulnerabilities in packages by performing the following:\n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**. In the \"Security\" section of the sidebar, click **Code security and analysis**.\n3. Verify that the Dependabot alerts is enabled and that **Enable by default for new repositories** is checked.\n\nIt is also recommended to verify that you're using another additional solution for package scanning because GitHub doesn't always recognize the vulnerabilities.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "1.5.6", - "Description": "Ensure scanners are in place for open-source license issues in used packages", + "Description": "Detect open-source license problems in used dependencies and fix them.", "Checks": [], "Attributes": [ { - "Section": "1.5", + "Section": "1 Source Code", + "Subsection": "1.5 Code Risks", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect open-source license problems in used dependencies and fix them.", @@ -1034,18 +1084,19 @@ "RemediationProcedure": "Designate a license scanning tool to identify open-source license problems and fix them and scan every package you use.", "AuditProcedure": "Ensure a license scanning tool is set up to identify open-source license problems and that every package you use is scanned by it.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.1", - "Description": "Ensure each pipeline has a single responsibility", + "Description": "Ensure each pipeline has a single responsibility in the build process.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Ensure each pipeline has a single responsibility in the build process.", @@ -1054,18 +1105,19 @@ "RemediationProcedure": "Divide each multi-responsibility pipeline into multiple pipelines, each having a single responsibility with the least privilege. Additionally, create all new pipelines with a sole purpose going forward.", "AuditProcedure": "For each pipeline, ensure it has only one responsibility in the build process.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs" + "References": "https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs", + "DefaultValue": "" } ] }, { "Id": "2.1.2", - "Description": "Ensure all aspects of the pipeline infrastructure and configuration are immutable", + "Description": "Ensure the pipeline orchestrator and its configuration are immutable.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure the pipeline orchestrator and its configuration are immutable.", @@ -1074,18 +1126,19 @@ "RemediationProcedure": "Use an immutable pipeline orchestrator and ensure that its configuration and all other aspects of the built environment are immutable, as well.", "AuditProcedure": "Verify that the pipeline orchestrator, its configuration, and all other aspects of the build environment are immutable.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.3", - "Description": "Ensure the build environment is logged", + "Description": "Keep build logs of the build environment detailing configuration and all activity within it. Also, consider to store them in a centralized organizational log store.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Keep build logs of the build environment detailing configuration and all activity within it. Also, consider to store them in a centralized organizational log store.", @@ -1094,18 +1147,19 @@ "RemediationProcedure": "Keep logs of the build environment. For example, use the .buildinfo file for Debian build workers. Also, store the logs in a centralized organizational log store.", "AuditProcedure": "Verify that the build environment is logged and stored in a centralized organizational log store.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.4", - "Description": "Ensure the creation of the build environment is automated", + "Description": "Automate the creation of the build environment.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Automate the creation of the build environment.", @@ -1114,18 +1168,19 @@ "RemediationProcedure": "Automate the deployment of the build environment.", "AuditProcedure": "Verify that the deployment of the build environment is automated and can be easily redeployed.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.5", - "Description": "Ensure access to build environments is limited", + "Description": "Restrict access to the build environment (orchestrator, pipeline executor, their environment, etc.) to trusted and qualified users only.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Restrict access to the build environment (orchestrator, pipeline executor, their environment, etc.) to trusted and qualified users only.", @@ -1134,18 +1189,19 @@ "RemediationProcedure": "Restrict access to the build environment to trusted and qualified users.", "AuditProcedure": "Verify each build environment is accessible only to known and authorized users.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.6", - "Description": "Ensure users must authenticate to access the build environment", + "Description": "Require users to login in to access the build environment - where the orchestrator, the pipeline executer, where the build workers are running, etc.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Require users to login in to access the build environment - where the orchestrator, the pipeline executer, where the build workers are running, etc.", @@ -1154,58 +1210,61 @@ "RemediationProcedure": "Require authentication to access the build environment and disable anonymous access.", "AuditProcedure": "Ensure authentication is required to access the build environment.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.7", - "Description": "Ensure build secrets are limited to the minimal necessary scope", + "Description": "Build tools providers offer a secure way to store secrets that should be used during the build process.\nThese secrets will often be credentials used to access other tools, for example for pulling code or for uploading artifacts.\nAccess to these secrets can be defined on various scopes, for example in github it could be on an organization level or a repository level and there is also control on whether these secrets are passed to forked pull request.\nTo protect these critical assets it is important to choose the most restrictive scope necessary.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 2", "AssessmentStatus": "Manual", - "Description": "Build tools providers offer a secure way to store secrets that should be used during the build process.\n These secrets will often be credentials used to access other tools, for example for pulling code or for uploading artifacts.\n Access to these secrets can be defined on various scopes, for example in github it could be on an organization level or a repository level and there is also control on whether these secrets are passed to forked pull request.\n To protect these critical assets it is important to choose the most restrictive scope necessary.", - "RationaleStatement": "Allowing over permissive access to these secrets may affect on their exposure.\n For example if a secret is defined in an organization level, and users can create new repositories, there is a scenario where a user can create a new repo and run a controlled build just to exfiltrate these secrets.", + "Description": "Build tools providers offer a secure way to store secrets that should be used during the build process.\nThese secrets will often be credentials used to access other tools, for example for pulling code or for uploading artifacts.\nAccess to these secrets can be defined on various scopes, for example in github it could be on an organization level or a repository level and there is also control on whether these secrets are passed to forked pull request.\nTo protect these critical assets it is important to choose the most restrictive scope necessary.", + "RationaleStatement": "Allowing over permissive access to these secrets may affect on their exposure.\nFor example if a secret is defined in an organization level, and users can create new repositories, there is a scenario where a user can create a new repo and run a controlled build just to exfiltrate these secrets.", "ImpactStatement": "Increased risk of exposure of build related secrets.", "RemediationProcedure": "For each build tool, review the secrets defined and their permissions scope and change over permissive scopes to more restrictive ones based on the required access.", "AuditProcedure": "For each build tool in use, review the secrets defined and the permission scopes they are assigned.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.8", - "Description": "Ensure the build infrastructure is automatically scanned for vulnerabilities", + "Description": "Scan the build infrastructure and its dependencies for vulnerabilities. It is recommended that this be done automatically.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Scan the build infrastructure and its dependencies for vulnerabilities. It is recommended that this be done automatically.", - "RationaleStatement": "Automatic scanning for vulnerabilities detects known vulnerabilities in the tooling used by the build infrastructure and its dependencies. These vulnerabilities can lead\n to a potentially massive breach if not handled as fast as possible, as attackers might also be\n aware of such vulnerabilities.", + "RationaleStatement": "Automatic scanning for vulnerabilities detects known vulnerabilities in the tooling used by the build infrastructure and its dependencies. These vulnerabilities can lead\nto a potentially massive breach if not handled as fast as possible, as attackers might also be\naware of such vulnerabilities.", "ImpactStatement": "", "RemediationProcedure": "Set an automated vulnerability scanning for your build infrastructure.", "AuditProcedure": "Verify that your build infrastructure is automatically scanned for vulnerabilities.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.9", - "Description": "Ensure default passwords are not used", + "Description": "Do not use default passwords of build tools and components.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Do not use default passwords of build tools and components.", @@ -1214,18 +1273,19 @@ "RemediationProcedure": "For each build tool, change the default password.", "AuditProcedure": "For each build tool, ensure the password used is not the default one.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.10", - "Description": "Ensure webhooks of the build environment are secured", + "Description": "Use secured webhooks of the build environment.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Use secured webhooks of the build environment.", @@ -1234,18 +1294,19 @@ "RemediationProcedure": "For each webhook in use, change it to secured (over HTTPS).", "AuditProcedure": "For each webhook in use, ensure it is secured (HTTPS).", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.1.11", - "Description": "Ensure minimum number of administrators are set for the build environment", + "Description": "Ensure the build environment has a minimum number of administrators.", "Checks": [], "Attributes": [ { - "Section": "2.1", + "Section": "2 Build Pipelines", + "Subsection": "2.1 Build Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure the build environment has a minimum number of administrators.", @@ -1254,18 +1315,19 @@ "RemediationProcedure": "Set the minimum number of administrators in the build environment.", "AuditProcedure": "Verify that the build environment has only the minimum number of administrators.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.1", - "Description": "Ensure build workers are single-used", + "Description": "Use a clean instance of build worker for every pipeline run.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Use a clean instance of build worker for every pipeline run.", @@ -1274,18 +1336,19 @@ "RemediationProcedure": "Create a clean build worker for every pipeline that is being run, or use build platform-hosted runners, as they typically offer a clean instance for every run.", "AuditProcedure": "Ensure that every pipeline that is being run has its own clean, new runner.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.2", - "Description": "Ensure build worker environments and commands are passed and not pulled", + "Description": "A worker’s environment can be passed (for example, a pod in a Kubernetes cluster in which an environment variable is passed to it). It also can be pulled, like a virtual machine that is installing a package. Ensure that the environment and commands are passed to the workers and not pulled from it.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "A worker’s environment can be passed (for example, a pod in a Kubernetes cluster in which an environment variable is passed to it). It also can be pulled, like a virtual machine that is installing a package. Ensure that the environment and commands are passed to the workers and not pulled from it.", @@ -1294,18 +1357,19 @@ "RemediationProcedure": "For each build worker, pass its environment and commands to it instead of pulling it.", "AuditProcedure": "For each build worker, ensure its environment and commands are passed and not pulled.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.3", - "Description": "Ensure the duties of each build worker are segregated", + "Description": "Separate responsibilities in the build workflow, such as testing, compiling, pushing artifacts, etc., to different build workers so that each worker will have a single duty.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Separate responsibilities in the build workflow, such as testing, compiling, pushing artifacts, etc., to different build workers so that each worker will have a single duty.", @@ -1314,18 +1378,19 @@ "RemediationProcedure": "For each build worker, limit its responsibility to one duty.", "AuditProcedure": "For each build worker, ensure it has the least responsibility possible, preferably only one duty.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.4", - "Description": "Ensure build workers have minimal network connectivity", + "Description": "Ensure that build workers have minimal network connectivity.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure that build workers have minimal network connectivity.", @@ -1334,18 +1399,19 @@ "RemediationProcedure": "Limit the network connectivity of build workers, environment, and any other components to the necessary minimum.", "AuditProcedure": "Verify that build workers, environment, and any other components have only the required minimum of network connectivity.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.5", - "Description": "Ensure run-time security is enforced for build workers", + "Description": "Add traces to build workers' operating systems and installed applications so that in run time, collected events can be analyzed to detect suspicious behavior patterns and malware.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Add traces to build workers' operating systems and installed applications so that in run time, collected events can be analyzed to detect suspicious behavior patterns and malware.", @@ -1354,18 +1420,19 @@ "RemediationProcedure": "Deploy and enforce a run-time security solution on build workers.", "AuditProcedure": "Verify that a run-time security solution is enforced on every active build worker.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.6", - "Description": "Ensure build workers are automatically scanned for vulnerabilities", + "Description": "Scan build workers for vulnerabilities. It is recommended that this be done automatically.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Scan build workers for vulnerabilities. It is recommended that this be done automatically.", @@ -1374,18 +1441,19 @@ "RemediationProcedure": "For each build worker, automatically scan its environmental sources, such as docker image, for vulnerabilities.", "AuditProcedure": "For each build worker, ensure the environmental sources it uses are scanned for vulnerabilities.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.7", - "Description": "Ensure build workers' deployment configuration is stored in a version control platform", + "Description": "Store the deployment configuration of build workers in a version control platform, such as Github.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Store the deployment configuration of build workers in a version control platform, such as Github.", @@ -1394,18 +1462,19 @@ "RemediationProcedure": "Document and store every deployment configuration of build workers in a version control platform.", "AuditProcedure": "Verify that the deployment configuration of build workers is stored in a version control platform.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.2.8", - "Description": "Ensure resource consumption of build workers is monitored", + "Description": "Monitor the resource consumption of build workers and set alerts for high consumption that can lead to resource exhaustion.", "Checks": [], "Attributes": [ { - "Section": "2.2", + "Section": "2 Build Pipelines", + "Subsection": "2.2 Build Worker", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Monitor the resource consumption of build workers and set alerts for high consumption that can lead to resource exhaustion.", @@ -1414,18 +1483,19 @@ "RemediationProcedure": "Set reources consumption monitoring for each build worker.", "AuditProcedure": "Verify that there is monitoring of resources consumption for each build worker.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.1", - "Description": "Ensure all build steps are defined as code", + "Description": "Use pipeline as code for build pipelines and their defined steps.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Use pipeline as code for build pipelines and their defined steps.", @@ -1434,18 +1504,19 @@ "RemediationProcedure": "Convert pipeline instructions into code-based syntax and upload them to the organization's version control platform.", "AuditProcedure": "Verify that all build steps are defined as code and stored in a version control system.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.2", - "Description": "Ensure steps have clearly defined build stage input and output", + "Description": "Define clear expected input and output for each build stage.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Define clear expected input and output for each build stage.", @@ -1454,18 +1525,19 @@ "RemediationProcedure": "For each build stage, clearly define what is expected for input and output.", "AuditProcedure": "For each build stage, verify that the expected input and output are clearly defined.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.3", - "Description": "Ensure output is written to a separate, secured storage repository", + "Description": "Write pipeline output artifacts to a secured storage repository.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Write pipeline output artifacts to a secured storage repository.", @@ -1474,18 +1546,19 @@ "RemediationProcedure": "For each pipeline that produces output artifacts, write them to a secured storage repository.", "AuditProcedure": "For each pipeline that produces output artifacts, ensure that they're written to a secured storage repository.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.4", - "Description": "Ensure changes to pipeline files are tracked and reviewed", + "Description": "Track and review changes to pipeline files.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Track and review changes to pipeline files.", @@ -1494,18 +1567,19 @@ "RemediationProcedure": "For each pipeline file, track changes to it and review them.", "AuditProcedure": "For each pipeline file, ensure changes to it are being tracked and reviewed.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.5", - "Description": "Ensure access to build process triggering is minimized", + "Description": "Restrict access to pipeline triggers.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Restrict access to pipeline triggers.", @@ -1514,18 +1588,19 @@ "RemediationProcedure": "For every pipeline in use, grant only the necessary users permission to trigger it.", "AuditProcedure": "For every pipeline in use, verify only the necessary users have permission to trigger it.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.6", - "Description": "Ensure pipelines are automatically scanned for misconfigurations", + "Description": "Scan the pipeline for misconfigurations. It is recommended that this be performed automatically.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Scan the pipeline for misconfigurations. It is recommended that this be performed automatically.", @@ -1534,18 +1609,19 @@ "RemediationProcedure": "For each pipeline, set automated misconfiguration scanning.", "AuditProcedure": "For each pipeline, verify that it is automatically scanned for misconfigurations.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.7", - "Description": "Ensure pipelines are automatically scanned for vulnerabilities", + "Description": "Scan pipelines for vulnerabilities. It is recommended that this be implemented automatically.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Scan pipelines for vulnerabilities. It is recommended that this be implemented automatically.", @@ -1554,18 +1630,19 @@ "RemediationProcedure": "For each pipeline, set automated vulnerability scanning.", "AuditProcedure": "For each pipeline, verify that it is automatically scanned for vulnerabilities.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.3.8", - "Description": "Ensure scanners are in place to identify and prevent sensitive data in pipeline files", + "Description": "Detect and prevent sensitive data, such as confidential ID numbers, passwords, etc., in pipelines.", "Checks": [], "Attributes": [ { - "Section": "2.3", + "Section": "2 Build Pipelines", + "Subsection": "2.3 Pipeline Instructions", "Profile": "Level 2", "AssessmentStatus": "Automated", "Description": "Detect and prevent sensitive data, such as confidential ID numbers, passwords, etc., in pipelines.", @@ -1574,18 +1651,40 @@ "RemediationProcedure": "For every pipeline that is in use, set scanners that will identify and prevent sensitive data within it.", "AuditProcedure": "For every pipeline that is in use, verify that scanners are set to identify and prevent the existence of sensitive data within it.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.4.1", - "Description": "Ensure all artifacts on all releases are signed", + "Description": "Sign all artifacts in all releases with user or organization keys.", "Checks": [], "Attributes": [ { - "Section": "2.4", + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", + "Profile": "Level 1", + "AssessmentStatus": "Manual", + "Description": "Sign all artifacts in all releases with user or organization keys.", + "RationaleStatement": "Signing artifacts is used to validate both their integrity and security. Organizations signal that artifacts may be trusted and they themselves produced them by ensuring that every artifact is properly signed. The presence of this signature also makes potentially malicious activity far more difficult.", + "ImpactStatement": "", + "RemediationProcedure": "For every artifact in every release, verify that all are properly signed.", + "AuditProcedure": "Ensure every artifact in every release is signed.", + "AdditionalInformation": "", + "References": "", + "DefaultValue": "" + } + ] + }, + { + "Id": "2.4.1", + "Description": "Sign all artifacts in all releases with user or organization keys.", + "Checks": [], + "Attributes": [ + { + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Sign all artifacts in all releases with user or organization keys.", @@ -1594,18 +1693,19 @@ "RemediationProcedure": "For every artifact in every release, verify that all are properly signed.", "AuditProcedure": "Ensure every artifact in every release is signed.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.4.2", - "Description": "Ensure all external dependencies used in the build process are locked", + "Description": "External dependencies may be public packages needed in the pipeline, or perhaps the public image being used for the build worker. Lock these external dependencies in every build pipeline.", "Checks": [], "Attributes": [ { - "Section": "2.4", + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "External dependencies may be public packages needed in the pipeline, or perhaps the public image being used for the build worker. Lock these external dependencies in every build pipeline.", @@ -1614,18 +1714,19 @@ "RemediationProcedure": "For all external dependencies being used in pipelines, verify they are locked.", "AuditProcedure": "Ensure every external dependency being used in pipelines is locked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://argon.io/blog/pipeline-composition-analysis-how-your-ci-pipeline-presents-new-opportunities-for-attackers/" + "References": "https://argon.io/blog/pipeline-composition-analysis-how-your-ci-pipeline-presents-new-opportunities-for-attackers/", + "DefaultValue": "" } ] }, { "Id": "2.4.3", - "Description": "Ensure dependencies are validated before being used", + "Description": "Validate every dependency of the pipeline before use.", "Checks": [], "Attributes": [ { - "Section": "2.4", + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Validate every dependency of the pipeline before use.", @@ -1634,18 +1735,19 @@ "RemediationProcedure": "For every dependency used in every pipeline, validate each one.", "AuditProcedure": "For every dependency used in every pipeline, ensure it has been validated.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.4.4", - "Description": "Ensure the build pipeline creates reproducible artifacts", + "Description": "Verify that the build pipeline creates reproducible artifacts, meaning that an artifact of the build pipeline is the same in every run when given the same input.", "Checks": [], "Attributes": [ { - "Section": "2.4", + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Verify that the build pipeline creates reproducible artifacts, meaning that an artifact of the build pipeline is the same in every run when given the same input.", @@ -1654,18 +1756,19 @@ "RemediationProcedure": "Create build pipelines that produce the same artifact given the same input (for example, artifacts that do not rely on timestamps).", "AuditProcedure": "Ensure that build pipelines create reproducible artifacts.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.4.5", - "Description": "Ensure pipeline steps produce a Software Bill of Materials (SBOM)", + "Description": "SBOM (Software Bill of Materials) is a file that specifies each component of software or a build process. Generate an SBOM after each run of a pipeline.", "Checks": [], "Attributes": [ { - "Section": "2.4", + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "SBOM (Software Bill of Materials) is a file that specifies each component of software or a build process. Generate an SBOM after each run of a pipeline.", @@ -1674,18 +1777,19 @@ "RemediationProcedure": "For each pipeline, configure it to produce a Software Bill of Materials on every run.", "AuditProcedure": "For each pipeline, ensure it produces a Software Bill of Materials on every run.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "2.4.6", - "Description": "Ensure pipeline steps sign the Software Bill of Materials (SBOM) produced", + "Description": "SBOM (Software Bill of Materials) is a file that specifies each component of software or a build process. It should be generated after every pipeline run. After it is generated, it must then be signed.", "Checks": [], "Attributes": [ { - "Section": "2.4", + "Section": "2 Build Pipelines", + "Subsection": "2.4 Pipeline Integrity", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "SBOM (Software Bill of Materials) is a file that specifies each component of software or a build process. It should be generated after every pipeline run. After it is generated, it must then be signed.", @@ -1694,38 +1798,40 @@ "RemediationProcedure": "For each pipeline, configure it to sign its produced Software Bill of Materials on every run.", "AuditProcedure": "For each pipeline, ensure it signs the Software Bill of Materials it produces on every run.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.1", - "Description": "Ensure third-party artifacts and open-source libraries are verified", + "Description": "Ensure third-party artifacts and open-source libraries in use are trusted and verified.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure third-party artifacts and open-source libraries in use are trusted and verified.", "RationaleStatement": "Verify third-party artifacts used in code are trusted and have not been infected by a malicious actor before use. This can be accomplished, for example, by comparing the checksum of the dependency to its checksum in a trusted source. If a difference arises, this may be a sign that someone interfered and added malicious code. If this dependency is used, it will infect the environment and could end in a massive breach, leaving the organization exposed to data leaks and more.", "ImpactStatement": "", - "RemediationProcedure": "Verify every GitHub action (building block of a GitHub workflow) in use by performing the following: \n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the left sidebar, click **Actions**, then click **General**.\n 4. Under \"Policies\", check **Allow OWNER, and select non-OWNER, actions and reusable workflows**, and then **Allow actions created by GitHub**.\n 5. Click **Save**.\n \n\n Alternatively, perform the following for each repository where GitHub actions are used:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the left sidebar, click **Actions**, then click **General**.\n 4. Under \"Actions permissions\", check **Allow OWNER, and select non-OWNER, actions and reusable workflows**, and then **Allow actions created by GitHub**.\n 5. Click **Save**.", - "AuditProcedure": "For every GitHub action (building block of a GitHub workflow), ensure verification before use by performing the following: \n \n\n 1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n 2. Next to the organization, click **Settings**.\n 3. In the left sidebar, click **Actions**, then click **General**.\n 4. Under \"Policies\", ensure **Allow OWNER, and select non-OWNER, actions and reusable workflows**, and **Allow actions created by GitHub** are checked.\n \n\n Alternatively, perform the following for each repository where GitHub actions are used:\n \n\n 1. On GitHub.com, navigate to the main page of the repository.\n 2. Under your repository name, click **Settings**.\n 3. In the left sidebar, click **Actions**, then click **General**.\n 4. Under \"Actions permissions\", ensure **Allow OWNER, and select non-OWNER, actions and reusable workflows** and **Allow actions created by GitHub** are checked.", + "RemediationProcedure": "Verify every GitHub action (building block of a GitHub workflow) in use by performing the following: \n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the left sidebar, click **Actions**, then click **General**.\n4. Under \"Policies\", check **Allow OWNER, and select non-OWNER, actions and reusable workflows**, and then **Allow actions created by GitHub**.\n5. Click **Save**.\n\nAlternatively, perform the following for each repository where GitHub actions are used:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the left sidebar, click **Actions**, then click **General**.\n4. Under \"Actions permissions\", check **Allow OWNER, and select non-OWNER, actions and reusable workflows**, and then **Allow actions created by GitHub**.\n5. Click **Save**.", + "AuditProcedure": "For every GitHub action (building block of a GitHub workflow), ensure verification before use by performing the following: \n\n1. In the top right corner of GitHub.com, click your profile photo, then click **Your organizations**.\n2. Next to the organization, click **Settings**.\n3. In the left sidebar, click **Actions**, then click **General**.\n4. Under \"Policies\", ensure **Allow OWNER, and select non-OWNER, actions and reusable workflows**, and **Allow actions created by GitHub** are checked.\n\nAlternatively, perform the following for each repository where GitHub actions are used:\n\n1. On GitHub.com, navigate to the main page of the repository.\n2. Under your repository name, click **Settings**.\n3. In the left sidebar, click **Actions**, then click **General**.\n4. Under \"Actions permissions\", ensure **Allow OWNER, and select non-OWNER, actions and reusable workflows** and **Allow actions created by GitHub** are checked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.2", - "Description": "Ensure Software Bill of Materials (SBOM) is required from all third-party suppliers", + "Description": "A Software Bill Of Materials (SBOM) is a file that specifies each component of software or a build process. Require an SBOM from every third-party provider.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "A Software Bill Of Materials (SBOM) is a file that specifies each component of software or a build process. Require an SBOM from every third-party provider.", @@ -1734,18 +1840,19 @@ "RemediationProcedure": "For every third-party dependency in use, require a Software Bill of Materials from its supplier.", "AuditProcedure": "For every third-party dependency in use, ensure it has a Software Bill of Materials.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.3", - "Description": "Ensure signed metadata of the build process is required and verified", + "Description": "Require and verify signed metadata of the build process for all dependencies in use.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Require and verify signed metadata of the build process for all dependencies in use.", @@ -1754,18 +1861,19 @@ "RemediationProcedure": "For each artifact in use, require and verify signed metadata of the build process.", "AuditProcedure": "For each artifact used, ensure it was supplied with verified and signed metadata of its build process. The signature should be the organizational signature and should be verifiable by common Certificate Authority servers.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.4", - "Description": "Ensure dependencies are monitored between open-source components", + "Description": "Monitor, or ask software suppliers to monitor, dependencies between open-source components in use.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Monitor, or ask software suppliers to monitor, dependencies between open-source components in use.", @@ -1774,18 +1882,19 @@ "RemediationProcedure": "For each open-source component, monitor its dependencies.", "AuditProcedure": "For each open-source component, ensure its dependencies are monitored.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.5", - "Description": "Ensure trusted package managers and repositories are defined and prioritized", + "Description": "Prioritize trusted package registries over others when pulling a package.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Prioritize trusted package registries over others when pulling a package.", @@ -1794,18 +1903,19 @@ "RemediationProcedure": "For each package to be downloaded, configure it to be downloaded from a trusted source.", "AuditProcedure": "For each package registry in use, ensure it is trusted.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.6", - "Description": "Ensure a signed Software Bill of Materials (SBOM) of the code is supplied", + "Description": "A Software Bill of Materials (SBOM) is a file that specifies each component of software or a build process. When using a dependency, demand its SBOM and ensure it is signed for validation purposes.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "A Software Bill of Materials (SBOM) is a file that specifies each component of software or a build process. When using a dependency, demand its SBOM and ensure it is signed for validation purposes.", @@ -1814,18 +1924,19 @@ "RemediationProcedure": "For every artifact supplied, require and verify a signed Software Bill of Materials from its supplier.", "AuditProcedure": "For every artifact supplied, ensure it has a validated, signed Software Bill of Materials.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.7", - "Description": "Ensure dependencies are pinned to a specific, verified version", + "Description": "Pin dependencies to a specific version. Avoid using the \"latest\" tag or broad version.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Pin dependencies to a specific version. Avoid using the \"latest\" tag or broad version.", @@ -1834,18 +1945,19 @@ "RemediationProcedure": "For every dependency in use, pin to a specific version.", "AuditProcedure": "For every dependency in use, ensure it is pinned to a specific version.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.1.8", - "Description": "Ensure all packages used are more than 60 days old", + "Description": "Use packages that are more than 60 days old.", "Checks": [], "Attributes": [ { - "Section": "3.1", + "Section": "3 Dependencies", + "Subsection": "3.1 Third-Party Packages", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Use packages that are more than 60 days old.", @@ -1854,18 +1966,19 @@ "RemediationProcedure": "If a package used is less than 60 days old, stop using it and find another solution.", "AuditProcedure": "For every package used, ensure it is more than 60 days old.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.2.1", - "Description": "Ensure an organization-wide dependency usage policy is enforced", + "Description": "Enforce a policy for dependency usage across the organization. For example, disallow the use of packages less than 60 days old.", "Checks": [], "Attributes": [ { - "Section": "3.2", + "Section": "3 Dependencies", + "Subsection": "3.2 Validate Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Enforce a policy for dependency usage across the organization. For example, disallow the use of packages less than 60 days old.", @@ -1874,18 +1987,19 @@ "RemediationProcedure": "Enforce policies for dependency usage across the organization.", "AuditProcedure": "Verify that a policy for dependency usage is enforced across the organization.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.2.2", - "Description": "Ensure packages are automatically scanned for known vulnerabilities", + "Description": "Automatically scan every package for vulnerabilities.", "Checks": [], "Attributes": [ { - "Section": "3.2", + "Section": "3 Dependencies", + "Subsection": "3.2 Validate Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Automatically scan every package for vulnerabilities.", @@ -1894,18 +2008,19 @@ "RemediationProcedure": "Set automatic scanning of packages for vulnerabilities.", "AuditProcedure": "Ensure automatic scanning of packages for vulnerabilities is enabled.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.2.3", - "Description": "Ensure packages are automatically scanned for license implications", + "Description": "A software license is a document that provides legal conditions and guidelines for the use and distribution of software, usually defined by the author. It is recommended to scan for any legal implications automatically.", "Checks": [], "Attributes": [ { - "Section": "3.2", + "Section": "3 Dependencies", + "Subsection": "3.2 Validate Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "A software license is a document that provides legal conditions and guidelines for the use and distribution of software, usually defined by the author. It is recommended to scan for any legal implications automatically.", @@ -1914,18 +2029,19 @@ "RemediationProcedure": "Set automatic package scanning for license implications.", "AuditProcedure": "Ensure license implication rules are configured and are scanned automatically.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "3.2.4", - "Description": "Ensure packages are automatically scanned for ownership change", + "Description": "Scan every package automatically for ownership change.", "Checks": [], "Attributes": [ { - "Section": "3.2", + "Section": "3 Dependencies", + "Subsection": "3.2 Validate Packages", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Scan every package automatically for ownership change.", @@ -1934,38 +2050,40 @@ "RemediationProcedure": "Set automatic scanning of packages for ownership change.", "AuditProcedure": "Ensure automatic scanning of packages for ownership change is set.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://blog.npmjs.org/post/182828408610/the-security-risks-of-changing-package-owners.html:https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident" + "References": "https://blog.npmjs.org/post/182828408610/the-security-risks-of-changing-package-owners.html:https://blog.npmjs.org/post/180565383195/details-about-the-event-stream-incident", + "DefaultValue": "" } ] }, { "Id": "4.1.1", - "Description": "Ensure all artifacts are signed by the build pipeline itself", + "Description": "Configure the build pipeline to sign every artifact it produces and verify that each artifact has the appropriate signature.", "Checks": [], "Attributes": [ { - "Section": "4.1", + "Section": "4 Artifacts", + "Subsection": "4.1 Verification", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Configure the build pipeline to sign every artifact it produces and verify that each artifact has the appropriate signature.", "RationaleStatement": "A cryptographic signature can be used to verify artifact authenticity. The signature created with a certain key is unique and not reversible, thus making it unique to the author. This means that an attacker tampering with a signed artifact will be noticed immediately using a simple verification step because the signature will change. Signing artifacts by the build pipeline that produces them ensures the integrity of those artifacts.", "ImpactStatement": "", - "RemediationProcedure": "Sign every artifact produced with the build pipeline that created it. Configure the build pipeline to sign each artifact.\n \n\n Steps from GitHub Documentation:\n \n\n You can follow the steps below to sign artifacts in GitHub actions. The trick involves loading in your private key into GitHub Actions using the gpg command-line commands.\n \n\n Export your gpg private key from the system that you have created it.\n Find your key-id (using gpg --list-secret-keys --keyid-format=long)\n Export the gpg secret key to an ASCII file using gpg --export-secret-keys -a > secret.txt\n Edit secret.txt using a plain text editor, and replace all newlines with a literal \"\\n\" until everything is on a single line\n Set up GitHub Actions secrets\n Create a secret called OSSRH_GPG_SECRET_KEY using the text from your edited secret.txt file (the whole text should be in a single line)\n Create a secret called OSSRH_GPG_SECRET_KEY_PASSWORD containing the password for your gpg secret key\n Create a GitHub Actions step to install the gpg secret key\n Add an action similar to:\n ```\n - id: install-secret-key\n name: Install gpg secret key\n run: |\n cat <(echo -e \"${{ secrets.OSSRH_GPG_SECRET_KEY }}\") | gpg --batch --import\n gpg --list-secret-keys --keyid-format LONG\n ```\n Verify that the secret key is shown in the GitHub Actions logs\n You can remove the output from list secret keys if you are confident that this action will work, but it is better to leave it in there\n Bring it all together, and create a GitHub Actions step to publish\n Add an action similar to:\n ```\n - id: publish-to-central\n name: Publish to Central Repository\n env:\n MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}\n MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}\n run: |\n mvn \\\n --no-transfer-progress \\\n --batch-mode \\\n -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} \\\n clean deploy\n ```\n After a couple of hours, verify that the artifact got published to The Central Repository", - "AuditProcedure": "Verify that the build pipeline signs every new artifact it produces and all artifacts are signed.\n \n\n There are many different signing tools or options each have there own method or commands to verify that the code or package created is signed.", + "RemediationProcedure": "Sign every artifact produced with the build pipeline that created it. Configure the build pipeline to sign each artifact.\n\nSteps from GitHub Documentation:\n\nYou can follow the steps below to sign artifacts in GitHub actions. The trick involves loading in your private key into GitHub Actions using the gpg command-line commands.\n\nExport your gpg private key from the system that you have created it.\nFind your key-id (using gpg --list-secret-keys --keyid-format=long)\nExport the gpg secret key to an ASCII file using gpg --export-secret-keys -a > secret.txt\nEdit secret.txt using a plain text editor, and replace all newlines with a literal \"\\n\" until everything is on a single line\nSet up GitHub Actions secrets\nCreate a secret called OSSRH_GPG_SECRET_KEY using the text from your edited secret.txt file (the whole text should be in a single line)\nCreate a secret called OSSRH_GPG_SECRET_KEY_PASSWORD containing the password for your gpg secret key\nCreate a GitHub Actions step to install the gpg secret key\nAdd an action similar to:\n```\n- id: install-secret-key\n name: Install gpg secret key\n run: |\n cat <(echo -e \"${{ secrets.OSSRH_GPG_SECRET_KEY }}\") | gpg --batch --import\n gpg --list-secret-keys --keyid-format LONG\n```\nVerify that the secret key is shown in the GitHub Actions logs\nYou can remove the output from list secret keys if you are confident that this action will work, but it is better to leave it in there\nBring it all together, and create a GitHub Actions step to publish\nAdd an action similar to:\n```\n- id: publish-to-central\n name: Publish to Central Repository\n env:\n MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}\n MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}\n run: |\n mvn \\\n --no-transfer-progress \\\n --batch-mode \\\n -Dgpg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} \\\n clean deploy\n```\nAfter a couple of hours, verify that the artifact got published to The Central Repository", + "AuditProcedure": "Verify that the build pipeline signs every new artifact it produces and all artifacts are signed.\n\nThere are many different signing tools or options each have there own method or commands to verify that the code or package created is signed.", "AdditionalInformation": "", - "DefaultValue": "Artifacts are not signed by Default.", - "References": "https://docs.github.com/en/code-security/supply-chain-security/end-to-end-supply-chain/securing-builds:https://gist.github.com/sualeh/ae78dc16123899d7942bc38baba5203c" + "References": "https://docs.github.com/en/code-security/supply-chain-security/end-to-end-supply-chain/securing-builds:https://gist.github.com/sualeh/ae78dc16123899d7942bc38baba5203c", + "DefaultValue": "Artifacts are not signed by Default." } ] }, { "Id": "4.1.2", - "Description": "Ensure artifacts are encrypted before distribution", + "Description": "Encrypt artifacts before they are distributed and ensure only trusted platforms have decryption capabilities.", "Checks": [], "Attributes": [ { - "Section": "4.1", + "Section": "4 Artifacts", + "Subsection": "4.1 Verification", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Encrypt artifacts before they are distributed and ensure only trusted platforms have decryption capabilities.", @@ -1974,18 +2092,19 @@ "RemediationProcedure": "Encrypt every artifact before distribution.", "AuditProcedure": "Ensure every artifact is encrypted before it is delivered.", "AdditionalInformation": "", - "DefaultValue": "Artifacts do not get encrypted by default.", - "References": "" + "References": "", + "DefaultValue": "Artifacts do not get encrypted by default." } ] }, { "Id": "4.1.3", - "Description": "Ensure only authorized platforms have decryption capabilities of artifacts", + "Description": "Grant decryption capabilities of artifacts only to trusted and authorized platforms.", "Checks": [], "Attributes": [ { - "Section": "4.1", + "Section": "4 Artifacts", + "Subsection": "4.1 Verification", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Grant decryption capabilities of artifacts only to trusted and authorized platforms.", @@ -1994,18 +2113,19 @@ "RemediationProcedure": "Grant decryption capabilities of the organization's artifacts only for trusted and authorized platforms.", "AuditProcedure": "Ensure only trusted and authorized platforms have decryption capabilities of the organization's artifacts.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.2.1", - "Description": "Ensure the authority to certify artifacts is limited", + "Description": "Software certification is used to verify the safety of certain software usage and to establish trust between the supplier and the consumer. Any artifact can be certified. Limit the authority to certify different artifacts.", "Checks": [], "Attributes": [ { - "Section": "4.2", + "Section": "4 Artifacts", + "Subsection": "4.2 Access to Artifacts", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Software certification is used to verify the safety of certain software usage and to establish trust between the supplier and the consumer. Any artifact can be certified. Limit the authority to certify different artifacts.", @@ -2014,18 +2134,19 @@ "RemediationProcedure": "Limit which artifact can be certified by which authority.", "AuditProcedure": "Ensure only certain artifacts can be certified by certain parties.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.2.2", - "Description": "Ensure number of permitted users who may upload new artifacts is minimized", + "Description": "Minimize ability to upload artifacts to the lowest number of trusted users possible.", "Checks": [], "Attributes": [ { - "Section": "4.2", + "Section": "4 Artifacts", + "Subsection": "4.2 Access to Artifacts", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Minimize ability to upload artifacts to the lowest number of trusted users possible.", @@ -2034,18 +2155,19 @@ "RemediationProcedure": "Allow only trusted and qualified users to upload new artifacts and limit them in number.", "AuditProcedure": "Ensure only trusted and qualified users can upload new artifacts, and that their number is the lowest possible.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.2.3", - "Description": "Ensure user access to the package registry utilizes Multi-Factor Authentication (MFA)", + "Description": "Enforce Multi-Factor Authentication (MFA) for user access to the package registry.", "Checks": [], "Attributes": [ { - "Section": "4.2", + "Section": "4 Artifacts", + "Subsection": "4.2 Access to Artifacts", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Enforce Multi-Factor Authentication (MFA) for user access to the package registry.", @@ -2054,18 +2176,19 @@ "RemediationProcedure": "For each package registry in use, enforce Multi-Factor Authentication as the only way to authenticate.", "AuditProcedure": "For each package registry in use, verify that Multi-Factor Authentication is enforced and is the only way to authenticate.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.2.4", - "Description": "Ensure user management of the package registry is not local", + "Description": "Manage users and their access to the package registry with an external authentication server and not with the package registry itself.", "Checks": [], "Attributes": [ { - "Section": "4.2", + "Section": "4 Artifacts", + "Subsection": "4.2 Access to Artifacts", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Manage users and their access to the package registry with an external authentication server and not with the package registry itself.", @@ -2074,118 +2197,124 @@ "RemediationProcedure": "For each package registry, use the main authentication server of the organization for user management and do not manage locally.", "AuditProcedure": "For each package registry, verify that its user access is not managed locally, but instead with the main authentication server of the organization.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.2.5", - "Description": "Ensure anonymous access to artifacts is revoked", + "Description": "For GitHub Private or Internal repositories anonymous access is not available. Verify that all repos that require access controls are Private or Internal.", "Checks": [], "Attributes": [ { - "Section": "4.2", + "Section": "4 Artifacts", + "Subsection": "4.2 Access to Artifacts", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "For GitHub Private or Internal repositories anonymous access is not available. Verify that all repos that require access controls are Private or Internal.", "RationaleStatement": "Disable the option to view artifacts as an anonymous user in order to protect private artifacts from being exposed.", "ImpactStatement": "Only logged and authorized users will be able to access artifacts.", - "RemediationProcedure": "Changing a repository's visibility\n \n\n 1. On your GitHub Enterprise Server instance, navigate to the main page of the repository.\n 1. Under your repository name, click Settings\n 1. Under \"Danger Zone\", to the right of to \"Change repository visibility\", click Change visibility.\n 1. Select a visibility.\n \n\n 1. Choose \n - Mark private\n - Make Internal\n \n\n 6. To verify that you're changing the correct repository's visibility, type the name of the repository you want to change the visibility of.", - "AuditProcedure": "To Audit the existing settings:\n \n\n 1. On your GitHub Enterprise Server instance, navigate to the main page of the repository.\n 1. Under your repository name, click Settings\n 3. Under \"Danger Zone\", to the right of to \"Change repository visibility\", click Change visibility.\n \n\n Review the current selection.", + "RemediationProcedure": "Changing a repository's visibility\n\n1. On your GitHub Enterprise Server instance, navigate to the main page of the repository.\n1. Under your repository name, click Settings\n1. Under \"Danger Zone\", to the right of to \"Change repository visibility\", click Change visibility.\n1. Select a visibility.\n\n1. Choose \n - Mark private\n - Make Internal\n\n6. To verify that you're changing the correct repository's visibility, type the name of the repository you want to change the visibility of.", + "AuditProcedure": "To Audit the existing settings:\n\n1. On your GitHub Enterprise Server instance, navigate to the main page of the repository.\n1. Under your repository name, click Settings\n3. Under \"Danger Zone\", to the right of to \"Change repository visibility\", click Change visibility.\n\nReview the current selection.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/enterprise-server@3.3/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/setting-repository-visibility" + "References": "https://docs.github.com/en/enterprise-server@3.3/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/setting-repository-visibility", + "DefaultValue": "" } ] }, { "Id": "4.2.6", - "Description": "Ensure minimum number of administrators are set for the package registry", + "Description": "Ensure the package registry has a minimum number of administrators.", "Checks": [], "Attributes": [ { - "Section": "4.2", + "Section": "4 Artifacts", + "Subsection": "4.2 Access to Artifacts", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Ensure the package registry has a minimum number of administrators.", "RationaleStatement": "Package registry admins have the ability to add/remove users, repositories, packages. Due to the permissive access granted to an admin, it is highly recommended to keep the number of administrator accounts as minimal as possible.", "ImpactStatement": "Administrator privileges are required to provide and maintain a secure and stable platform but allowing extraneous administrator accounts can create a vulnerability.", - "RemediationProcedure": "Set the minimum number of administrators in your package registry.\n \n\n To accomplish this:\n \n\n For each repository that you administer on GitHub, you can see an overview of every team or person with access to the repository. From the overview, choose Manage access and provide access to the appropriate people or teams.", - "AuditProcedure": "Verify that your package registry has only the minimum number of administrators.\n \n\n For each repository that you administer on GitHub, you can see an overview of every team or person with access to the repository. From the overview, you can also invite new teams or people, change each team or person's role for the repository, or remove access to the repository.", + "RemediationProcedure": "Set the minimum number of administrators in your package registry.\n\nTo accomplish this:\n\nFor each repository that you administer on GitHub, you can see an overview of every team or person with access to the repository. From the overview, choose Manage access and provide access to the appropriate people or teams.", + "AuditProcedure": "Verify that your package registry has only the minimum number of administrators.\n\nFor each repository that you administer on GitHub, you can see an overview of every team or person with access to the repository. From the overview, you can also invite new teams or people, change each team or person's role for the repository, or remove access to the repository.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/managing-teams-and-people-with-access-to-your-repository" + "References": "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/managing-repository-settings/managing-teams-and-people-with-access-to-your-repository", + "DefaultValue": "" } ] }, { "Id": "4.3.1", - "Description": "Ensure all signed artifacts are validated upon uploading the package registry", + "Description": "Validate artifact signatures before uploading to the package registry.", "Checks": [], "Attributes": [ { - "Section": "4.3", + "Section": "4 Artifacts", + "Subsection": "4.3 Package Registries", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Validate artifact signatures before uploading to the package registry.", "RationaleStatement": "Cryptographic signature is a tool to verify artifact authenticity. Every artifact is supposed to be signed by its creator in order to confirm that it was not compromised before reaching the client. Validating an artifact signature before delivering it is another level of protection which ensures the signature has not been changed, meaning no one tried or succeeded in tampering with the artifact. This creates trust between the supplier and the client.", "ImpactStatement": "", "RemediationProcedure": "Validate every artifact with its signature before uploading it to the package registry. It is recommended to do so automatically.", - "AuditProcedure": "Ensure every artifact in the package registry has been validated with its signature.\n \n\n 1. On GitHub, navigate to a pull request\n 2. On the pull request, click <> Commits and view the detailed information regarding the signature.", + "AuditProcedure": "Ensure every artifact in the package registry has been validated with its signature.\n\n1. On GitHub, navigate to a pull request\n2. On the pull request, click <> Commits and view the detailed information regarding the signature.", "AdditionalInformation": "", - "DefaultValue": "Artifacts are not scanned by default.", - "References": "https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification:https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits" + "References": "https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification:https://docs.github.com/en/authentication/managing-commit-signature-verification/signing-commits", + "DefaultValue": "Artifacts are not scanned by default." } ] }, { "Id": "4.3.2", - "Description": "Ensure all versions of an existing artifact have their signatures validated", + "Description": "Validate the signature of all versions of an existing artifact.", "Checks": [], "Attributes": [ { - "Section": "4.3", + "Section": "4 Artifacts", + "Subsection": "4.3 Package Registries", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Validate the signature of all versions of an existing artifact.", "RationaleStatement": "In order to be certain a version of an existing and trusted artifact is not malicious or delivered by someone looking to interfere with the supply chain, it is a good practice to validate the signatures of each version. Doing so decreases the risk of using a compromised artifact, which might lead to a breach.", "ImpactStatement": "", "RemediationProcedure": "For each artifact, sign and validate each version before uploading or using the artifact.", - "AuditProcedure": "For each artifact, ensure that all of its versions are signed and validated before it is uploaded or used.\n \n\n Ensure every artifact in the package registry has been validated with its signature.\n \n\n On GitHub, navigate to a pull request\n On the pull request, click <> Commits and view the detailed information regarding the signature.", + "AuditProcedure": "For each artifact, ensure that all of its versions are signed and validated before it is uploaded or used.\n\nEnsure every artifact in the package registry has been validated with its signature.\n\nOn GitHub, navigate to a pull request\nOn the pull request, click <> Commits and view the detailed information regarding the signature.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.3.3", - "Description": "Ensure changes in package registry configuration are audited", + "Description": "Audit changes of the package registry configuration.", "Checks": [], "Attributes": [ { - "Section": "4.3", + "Section": "4 Artifacts", + "Subsection": "4.3 Package Registries", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Audit changes of the package registry configuration.", "RationaleStatement": "The package registry is a crucial component in the software supply chain. It stores artifacts with potentially sensitive data that will eventually be deployed and used in production. Every change made to the package registry configuration must be examined carefully to ensure no exposure of the registry's sensitive data. This examination also ensures no malicious actors have performed modifications to a stored artifact. Auditing the configuration and its changes helps in decreasing such risks.", "ImpactStatement": "", "RemediationProcedure": "Audit the changes to the package registry configuration.", - "AuditProcedure": "Verify that all changes to the packages registry configuration are audited.\n \n\n Search the audit log with\n \n\n repo category actions", + "AuditProcedure": "Verify that all changes to the packages registry configuration are audited.\n\nSearch the audit log with\n\nrepo category actions", "AdditionalInformation": "", - "DefaultValue": "GitHub audits this by default.", - "References": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/reviewing-the-audit-log-for-your-organization" + "References": "https://docs.github.com/en/organizations/keeping-your-organization-secure/managing-security-settings-for-your-organization/reviewing-the-audit-log-for-your-organization", + "DefaultValue": "GitHub audits this by default." } ] }, { "Id": "4.3.4", - "Description": "Ensure webhooks of the repository are secured", + "Description": "Use secured webhooks to reduce the possibility of malicious payloads.", "Checks": [], "Attributes": [ { - "Section": "4.3", + "Section": "4 Artifacts", + "Subsection": "4.3 Package Registries", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Use secured webhooks to reduce the possibility of malicious payloads.", @@ -2194,18 +2323,19 @@ "RemediationProcedure": "For each webhook in use, change it to secured (over HTTPS).", "AuditProcedure": "", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "4.4.1", - "Description": "Ensure artifacts contain information about their origin", + "Description": "When delivering artifacts, ensure they have information about their origin. This may be done by providing a Software Bill of Manufacture (SBOM) or some metadata files.", "Checks": [], "Attributes": [ { - "Section": "4.4", + "Section": "4 Artifacts", + "Subsection": "4.4 Origin Traceability", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "When delivering artifacts, ensure they have information about their origin. This may be done by providing a Software Bill of Manufacture (SBOM) or some metadata files.", @@ -2214,18 +2344,19 @@ "RemediationProcedure": "For each artifact supplied, supply information about its origin. For each artifact in use, ask for information about its origin.", "AuditProcedure": "For each artifact, ensure it has information about its origin.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.1", - "Description": "Ensure deployment configuration files are separated from source code", + "Description": "Deployment configurations are often stored in a version control system. Separate deployment configuration files from source code repositories.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Deployment configurations are often stored in a version control system. Separate deployment configuration files from source code repositories.", @@ -2234,18 +2365,19 @@ "RemediationProcedure": "Store each deployment configuration file in a dedicated repository separately from source code.", "AuditProcedure": "Ensure each deployment configuration file is stored separately from source code.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.2", - "Description": "Ensure changes in deployment configuration are audited", + "Description": "Audit and track changes made in deployment configuration.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Audit and track changes made in deployment configuration.", @@ -2254,18 +2386,19 @@ "RemediationProcedure": "For each deployment configuration, track and audit changes made to it.", "AuditProcedure": "For each deployment configuration, ensure changes made to it are audited and tracked.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.3", - "Description": "Ensure scanners are in place to identify and prevent sensitive data in deployment configuration", + "Description": "Detect and prevent sensitive data – such as confidential ID numbers, passwords, etc. – in deployment configurations.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Detect and prevent sensitive data – such as confidential ID numbers, passwords, etc. – in deployment configurations.", @@ -2274,18 +2407,19 @@ "RemediationProcedure": "For each deployment configuration file, set scanners to identify and prevent sensitive data within it.", "AuditProcedure": "For each deployment configuration file, verify that scanners are set to identify and prevent the existence of sensitive data within it.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.4", - "Description": "Limit access to deployment configurations", + "Description": "Restrict access to the deployment configuration to trusted and qualified users only.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Restrict access to the deployment configuration to trusted and qualified users only.", @@ -2294,18 +2428,19 @@ "RemediationProcedure": "Restrict access to the deployment configuration to trusted and qualified users.", "AuditProcedure": "Verify each deployment configuration is accessible only to known and authorized users.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.5", - "Description": "Scan Infrastructure as Code (IaC)", + "Description": "Detect and prevent misconfigurations or insecure instructions in Infrastructure as Code (IaC) files, such as Terraform files.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 2", "AssessmentStatus": "Manual", "Description": "Detect and prevent misconfigurations or insecure instructions in Infrastructure as Code (IaC) files, such as Terraform files.", @@ -2314,18 +2449,19 @@ "RemediationProcedure": "For every Infrastructure as Code (IaC) instructions file, set scanners to identify and prevent misconfigurations and insecure instructions.", "AuditProcedure": "For every Infrastructure as Code (IaC) instructions file, verify that scanners are set to identify and prevent misconfigurations and insecure instructions.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.6", - "Description": "Ensure deployment configuration manifests are verified", + "Description": "Verify the deployment configuration manifests.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Verify the deployment configuration manifests.", @@ -2334,18 +2470,19 @@ "RemediationProcedure": "Verify each deployment configuration manifest in use.", "AuditProcedure": "For each deployment configuration manifest in use, ensure it has been verified.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.1.7", - "Description": "Ensure deployment configuration manifests are pinned to a specific, verified version", + "Description": "Deployment configuration is often stored in a version control system and is pulled from there. Pin the configuration used to a specific, verified version or commit Secure Hash Algorithm (SHA). Avoid referring configuration without its version tag specified.", "Checks": [], "Attributes": [ { - "Section": "5.1", + "Section": "5 Deployment", + "Subsection": "5.1 Deployment Configuration", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Deployment configuration is often stored in a version control system and is pulled from there. Pin the configuration used to a specific, verified version or commit Secure Hash Algorithm (SHA). Avoid referring configuration without its version tag specified.", @@ -2354,18 +2491,19 @@ "RemediationProcedure": "For every deployment configuration manifest in use, pin to a specific version or commit Secure Hash Algorithm (SHA).", "AuditProcedure": "For every deployment configuration manifest in use, ensure it is pinned to a specific version or commit Secure Hash Algorithm (SHA).", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.2.1", - "Description": "Ensure deployments are automated", + "Description": "Automate deployments of production environment and application.", "Checks": [], "Attributes": [ { - "Section": "5.2", + "Section": "5 Deployment", + "Subsection": "5.2 Deployment Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Automate deployments of production environment and application.", @@ -2374,18 +2512,19 @@ "RemediationProcedure": "Automate each deployment process of the production environment and application.", "AuditProcedure": "For each deployment process, ensure it is automated.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.2.2", - "Description": "Ensure the deployment environment is reproducible", + "Description": "Verify that the deployment environment – the orchestrator and the production environment where the application is deployed – is reproducible. This means that the environment stays the same in each deployment if the configuration has not changed.", "Checks": [], "Attributes": [ { - "Section": "5.2", + "Section": "5 Deployment", + "Subsection": "5.2 Deployment Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Verify that the deployment environment – the orchestrator and the production environment where the application is deployed – is reproducible. This means that the environment stays the same in each deployment if the configuration has not changed.", @@ -2394,18 +2533,19 @@ "RemediationProcedure": "Adjust the process that deploys the deployment/production environment to build the same environment each time when the configuration has not changed.", "AuditProcedure": "Verify that the deployment/production environment is reproducible.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.2.3", - "Description": "Ensure access to production environment is limited", + "Description": "Restrict access to the production environment to a few trusted and qualified users only.", "Checks": [], "Attributes": [ { - "Section": "5.2", + "Section": "5 Deployment", + "Subsection": "5.2 Deployment Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Restrict access to the production environment to a few trusted and qualified users only.", @@ -2414,18 +2554,19 @@ "RemediationProcedure": "Restrict access to the production environment to trusted and qualified users.", "AuditProcedure": "Verify that the production environment is accessible only to trusted and qualified users.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] }, { "Id": "5.2.4", - "Description": "Ensure default passwords are not used", + "Description": "Do not use default passwords of deployment tools and components.", "Checks": [], "Attributes": [ { - "Section": "5.2", + "Section": "5 Deployment", + "Subsection": "5.2 Deployment Environment", "Profile": "Level 1", "AssessmentStatus": "Manual", "Description": "Do not use default passwords of deployment tools and components.", @@ -2434,8 +2575,8 @@ "RemediationProcedure": "For each deployment tool, change the password.", "AuditProcedure": "For each deployment tool, ensure the password is not the default one.", "AdditionalInformation": "", - "DefaultValue": "", - "References": "" + "References": "", + "DefaultValue": "" } ] } diff --git a/util/generate_compliance_json_from_csv_for_cis10_github.py b/util/generate_compliance_json_from_csv_for_cis10_github.py index 3297c70640..7b925a53c2 100644 --- a/util/generate_compliance_json_from_csv_for_cis10_github.py +++ b/util/generate_compliance_json_from_csv_for_cis10_github.py @@ -10,13 +10,14 @@ import sys file_name = sys.argv[1] # read the CSV file rows and use the column fields to form the Prowler compliance JSON file 'cis_1.0_github.json' -output = {"Framework": "CIS-GitHub", "Version": "1.5", "Requirements": []} +output = {"Framework": "CIS-GitHub", "Version": "1.0", "Requirements": []} with open(file_name, newline="", encoding="utf-8") as f: - reader = csv.reader(f, delimiter=",") + reader = csv.reader(f, delimiter=";") for row in reader: attribute = { - "Section": row[3], - "Profile": row[4], + "Section": row[0], + "Subsection": row[1], + "Profile": row[3], "AssessmentStatus": row[5], "Description": row[6], "RationaleStatement": row[7], @@ -24,17 +25,19 @@ with open(file_name, newline="", encoding="utf-8") as f: "RemediationProcedure": row[9], "AuditProcedure": row[10], "AdditionalInformation": row[11], - "References": row[12], + "References": row[25], + "DefaultValue": row[26], } output["Requirements"].append( { - "Id": row[0], - "Description": row[1], - "Checks": list(map(str.strip, row[2].split(","))), + "Id": row[2], + "Description": row[6], + "Checks": [], "Attributes": [attribute], } ) + # Write the output Prowler compliance JSON file 'cis_1.0_github.json' locally with open("cis_1.0_github.json", "w", encoding="utf-8") as outfile: json.dump(output, outfile, indent=4, ensure_ascii=False) From dfdd45e4d053d92b94426b2b79049e1c9c16dfbb Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 14 Aug 2025 10:38:38 +0200 Subject: [PATCH 19/30] fix(github): list all accessible repositories (#8522) --- .../github/getting-started-github.md | 25 +- .../github/img/github-pat-permissions.png | Bin 0 -> 91448 bytes prowler/CHANGELOG.md | 1 + prowler/providers/github/github_provider.py | 6 + .../services/repository/repository_service.py | 381 +++++++++++------- .../repository/repository_service_test.py | 295 +++++--------- 6 files changed, 350 insertions(+), 358 deletions(-) create mode 100644 docs/tutorials/github/img/github-pat-permissions.png diff --git a/docs/tutorials/github/getting-started-github.md b/docs/tutorials/github/getting-started-github.md index d0190a3adf..b4f22d0366 100644 --- a/docs/tutorials/github/getting-started-github.md +++ b/docs/tutorials/github/getting-started-github.md @@ -37,26 +37,31 @@ Personal Access Tokens provide the simplest GitHub authentication method and sup - **Expiration**: Set an appropriate expiration date (recommended: 90 days or less) - **Repository access**: Choose "All repositories" or "Only select repositories" based on your needs + ???+ note "Public repositories" + Even if you select 'Only select repositories', the token will have access to the public repositories that you own or are a member of. + 5. **Configure Token Permissions** To enable Prowler functionality, configure the following permissions: - **Repository permissions:** - - **Contents**: Read-only access - - **Metadata**: Read-only access - - **Pull requests**: Read-only access - - **Security events**: Read-only access - - **Statuses**: Read-only access + - **Repository permissions:** + - **Contents**: Read-only access + - **Metadata**: Read-only access + - **Pull requests**: Read-only access + - **Security advisories**: Read-only access + - **Statuses**: Read-only access - **Organization permissions:** - - **Members**: Read-only access + - **Organization permissions:** + - **Members**: Read-only access - **Account permissions:** - - **Email addresses**: Read-only access + - **Account permissions:** + - **Email addresses**: Read-only access 6. **Copy and Store the Token** - Copy the generated token immediately (GitHub displays tokens only once) - Store tokens securely using environment variables +![GitHub Personal Access Token Permissions](./img/github-pat-permissions.png) + #### **Option 2: Create a Classic Personal Access Token (Not Recommended)** ???+ warning "Security Risk" diff --git a/docs/tutorials/github/img/github-pat-permissions.png b/docs/tutorials/github/img/github-pat-permissions.png new file mode 100644 index 0000000000000000000000000000000000000000..d666c70baaed3c155c57936888270ace1bd02eb4 GIT binary patch literal 91448 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 S#n%hqkEFQV list[str]: + """ + Use the GitHub GraphQL API to list all repositories that the authentication token has access to. + This works with high-granularity (fine-grained) PATs. + """ + graphql_url = "https://api.github.com/graphql" + token = self.provider.session.token + headers = { + "Authorization": f"bearer {token}", + "Content-Type": "application/json", + } + query = """ + { + viewer { + repositories(first: 100, affiliations: [OWNER, ORGANIZATION_MEMBER]) { + nodes { + nameWithOwner + } + } + } + } + """ + + try: + response = requests.post( + graphql_url, json={"query": query}, headers=headers + ) + response.raise_for_status() + data = response.json() + + if "errors" in data: + logger.error(f"Error in GraphQL query: {data['errors']}") + return [] + + repo_nodes = ( + data.get("data", {}) + .get("viewer", {}) + .get("repositories", {}) + .get("nodes", []) + ) + return [repo["nameWithOwner"] for repo in repo_nodes] + + except requests.exceptions.RequestException as error: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + return [] + def _list_repositories(self): """ List repositories based on provider scoping configuration. - - Scoping behavior: - - No scoping: Returns all accessible repositories for authenticated user - - Repository scoping: Returns only specified repositories - Example: --repository owner1/repo1 owner2/repo2 - - Organization scoping: Returns all repositories from specified organizations - Example: --organization org1 org2 - - Combined scoping: Returns specified repositories + all repos from organizations - Example: --repository owner1/repo1 --organization org2 - - Returns: - dict: Dictionary of repository ID to Repo objects - - Raises: - github.GithubException: When GitHub API access fails - github.RateLimitExceededException: When API rate limits are exceeded """ logger.info("Repository - Listing Repositories...") repos = {} @@ -109,11 +142,38 @@ class Repository(GithubService): error, "processing organization", org_name ) else: - for repo in client.get_user().get_repos(): - self._process_repository(repo, repos) + logger.info( + "No repository or organization specified, discovering accessible repositories via GraphQL API..." + ) + accessible_repo_names = self._get_accessible_repos_graphql() + + if not accessible_repo_names: + logger.warning( + "Could not find any accessible repositories with the provided token." + ) + + for repo_name in accessible_repo_names: + try: + repo = client.get_repo(repo_name) + logger.info( + f"Processing repository found via GraphQL: {repo.full_name}" + ) + self._process_repository(repo, repos) + except Exception as error: + if hasattr(self, "_handle_github_api_error"): + self._handle_github_api_error( + error, + "accessing repository discovered via GraphQL", + repo_name, + ) + else: + logger.error( + f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + except github.RateLimitExceededException as error: logger.error(f"GitHub API rate limit exceeded: {error}") - raise # Re-raise rate limit errors as they need special handling + raise except github.GithubException as error: logger.error(f"GitHub API error while listing repositories: {error}") except Exception as error: @@ -124,158 +184,167 @@ class Repository(GithubService): def _process_repository(self, repo, repos): """Process a single repository and extract all its information.""" - default_branch = repo.default_branch - securitymd_exists = self._file_exists(repo, "SECURITY.md") - # CODEOWNERS file can be in .github/, root, or docs/ - # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-file-location - codeowners_paths = [ - ".github/CODEOWNERS", - "CODEOWNERS", - "docs/CODEOWNERS", - ] - codeowners_files = [self._file_exists(repo, path) for path in codeowners_paths] - if True in codeowners_files: - codeowners_exists = True - elif all(file is None for file in codeowners_files): - codeowners_exists = None - else: - codeowners_exists = False - delete_branch_on_merge = ( - repo.delete_branch_on_merge - if repo.delete_branch_on_merge is not None - else False - ) - - require_pr = False - approval_cnt = 0 - branch_protection = False - required_linear_history = False - allow_force_pushes = True - branch_deletion = True - require_code_owner_reviews = False - require_signed_commits = False - status_checks = False - enforce_admins = False - conversation_resolution = False try: - branch = repo.get_branch(default_branch) - if branch.protected: - protection = branch.get_protection() - if protection: - require_pr = protection.required_pull_request_reviews is not None - approval_cnt = ( - protection.required_pull_request_reviews.required_approving_review_count - if require_pr - else 0 - ) - required_linear_history = protection.required_linear_history - allow_force_pushes = protection.allow_force_pushes - branch_deletion = protection.allow_deletions - status_checks = protection.required_status_checks is not None - enforce_admins = protection.enforce_admins - conversation_resolution = ( - protection.required_conversation_resolution - ) - branch_protection = True - require_code_owner_reviews = ( - protection.required_pull_request_reviews.require_code_owner_reviews - if require_pr - else False - ) - require_signed_commits = branch.get_required_signatures() - except Exception as error: - # If the branch is not found, it is not protected - if "404" in str(error): - logger.warning( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) - # Any other error, we cannot know if the branch is protected or not + default_branch = repo.default_branch + securitymd_exists = self._file_exists(repo, "SECURITY.md") + # CODEOWNERS file can be in .github/, root, or docs/ + # https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners#codeowners-file-location + codeowners_paths = [ + ".github/CODEOWNERS", + "CODEOWNERS", + "docs/CODEOWNERS", + ] + codeowners_files = [ + self._file_exists(repo, path) for path in codeowners_paths + ] + if True in codeowners_files: + codeowners_exists = True + elif all(file is None for file in codeowners_files): + codeowners_exists = None else: - require_pr = None - approval_cnt = None - branch_protection = None - required_linear_history = None - allow_force_pushes = None - branch_deletion = None - require_code_owner_reviews = None - require_signed_commits = None - status_checks = None - enforce_admins = None - conversation_resolution = None - logger.error( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" - ) + codeowners_exists = False + delete_branch_on_merge = ( + repo.delete_branch_on_merge + if repo.delete_branch_on_merge is not None + else False + ) - secret_scanning_enabled = False - dependabot_alerts_enabled = False - try: - if ( - repo.security_and_analysis - and repo.security_and_analysis.secret_scanning - ): - secret_scanning_enabled = ( - repo.security_and_analysis.secret_scanning.status == "enabled" - ) + require_pr = False + approval_cnt = 0 + branch_protection = False + required_linear_history = False + allow_force_pushes = True + branch_deletion = True + require_code_owner_reviews = False + require_signed_commits = False + status_checks = False + enforce_admins = False + conversation_resolution = False try: - # Use get_dependabot_alerts to check if Dependabot alerts are enabled - repo.get_dependabot_alerts().totalCount - # If the call succeeds, Dependabot is enabled (even if no alerts) - dependabot_alerts_enabled = True + branch = repo.get_branch(default_branch) + if branch.protected: + protection = branch.get_protection() + if protection: + require_pr = ( + protection.required_pull_request_reviews is not None + ) + approval_cnt = ( + protection.required_pull_request_reviews.required_approving_review_count + if require_pr + else 0 + ) + required_linear_history = protection.required_linear_history + allow_force_pushes = protection.allow_force_pushes + branch_deletion = protection.allow_deletions + status_checks = protection.required_status_checks is not None + enforce_admins = protection.enforce_admins + conversation_resolution = ( + protection.required_conversation_resolution + ) + branch_protection = True + require_code_owner_reviews = ( + protection.required_pull_request_reviews.require_code_owner_reviews + if require_pr + else False + ) + require_signed_commits = branch.get_required_signatures() except Exception as error: - error_str = str(error) - if ( - "403" in error_str - and "Dependabot alerts are disabled for this repository." - in error_str - ): - dependabot_alerts_enabled = False - else: - logger.error( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + # If the branch is not found, it is not protected + if "404" in str(error): + logger.warning( + f"{repo.full_name}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - dependabot_alerts_enabled = None + # Any other error, we cannot know if the branch is protected or not + else: + require_pr = None + approval_cnt = None + branch_protection = None + required_linear_history = None + allow_force_pushes = None + branch_deletion = None + require_code_owner_reviews = None + require_signed_commits = None + status_checks = None + enforce_admins = None + conversation_resolution = None + logger.error( + f"{repo.full_name}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + + secret_scanning_enabled = False + dependabot_alerts_enabled = False + try: + if ( + repo.security_and_analysis + and repo.security_and_analysis.secret_scanning + ): + secret_scanning_enabled = ( + repo.security_and_analysis.secret_scanning.status == "enabled" + ) + try: + # Use get_dependabot_alerts to check if Dependabot alerts are enabled + repo.get_dependabot_alerts().totalCount + # If the call succeeds, Dependabot is enabled (even if no alerts) + dependabot_alerts_enabled = True + except Exception as error: + error_str = str(error) + if ( + "403" in error_str + and "Dependabot alerts are disabled for this repository." + in error_str + ): + dependabot_alerts_enabled = False + else: + logger.error( + f"{repo.full_name}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + dependabot_alerts_enabled = None + except Exception as error: + logger.error( + f"{repo.full_name}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + ) + secret_scanning_enabled = None + dependabot_alerts_enabled = None + repos[repo.id] = Repo( + id=repo.id, + name=repo.name, + owner=repo.owner.login, + full_name=repo.full_name, + default_branch=Branch( + name=default_branch, + protected=branch_protection, + default_branch=True, + require_pull_request=require_pr, + approval_count=approval_cnt, + required_linear_history=required_linear_history, + allow_force_pushes=allow_force_pushes, + branch_deletion=branch_deletion, + status_checks=status_checks, + enforce_admins=enforce_admins, + conversation_resolution=conversation_resolution, + require_code_owner_reviews=require_code_owner_reviews, + require_signed_commits=require_signed_commits, + ), + private=repo.private, + archived=repo.archived, + pushed_at=repo.pushed_at, + securitymd=securitymd_exists, + codeowners_exists=codeowners_exists, + secret_scanning_enabled=secret_scanning_enabled, + dependabot_alerts_enabled=dependabot_alerts_enabled, + delete_branch_on_merge=delete_branch_on_merge, + ) except Exception as error: logger.error( - f"{error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" + f"{repo.full_name}: {error.__class__.__name__}[{error.__traceback__.tb_lineno}]: {error}" ) - secret_scanning_enabled = None - dependabot_alerts_enabled = None - repos[repo.id] = Repo( - id=repo.id, - name=repo.name, - owner=repo.owner.login, - full_name=repo.full_name, - default_branch=Branch( - name=default_branch, - protected=branch_protection, - default_branch=True, - require_pull_request=require_pr, - approval_count=approval_cnt, - required_linear_history=required_linear_history, - allow_force_pushes=allow_force_pushes, - branch_deletion=branch_deletion, - status_checks=status_checks, - enforce_admins=enforce_admins, - conversation_resolution=conversation_resolution, - require_code_owner_reviews=require_code_owner_reviews, - require_signed_commits=require_signed_commits, - ), - private=repo.private, - archived=repo.archived, - pushed_at=repo.pushed_at, - securitymd=securitymd_exists, - codeowners_exists=codeowners_exists, - secret_scanning_enabled=secret_scanning_enabled, - dependabot_alerts_enabled=dependabot_alerts_enabled, - delete_branch_on_merge=delete_branch_on_merge, - ) class Branch(BaseModel): """Model for Github Branch""" name: str - protected: bool + protected: Optional[bool] default_branch: bool require_pull_request: Optional[bool] approval_count: Optional[int] diff --git a/tests/providers/github/services/repository/repository_service_test.py b/tests/providers/github/services/repository/repository_service_test.py index ada89ee072..20e5887d54 100644 --- a/tests/providers/github/services/repository/repository_service_test.py +++ b/tests/providers/github/services/repository/repository_service_test.py @@ -1,6 +1,7 @@ from datetime import datetime, timezone from unittest.mock import MagicMock, patch +import requests from github import GithubException, RateLimitExceededException from prowler.providers.github.services.repository.repository_service import ( @@ -40,6 +41,7 @@ def mock_list_repositories(_): archived=False, pushed_at=datetime.now(timezone.utc), delete_branch_on_merge=True, + dependabot_alerts_enabled=True, ), } @@ -110,6 +112,105 @@ class Test_Repository_FileExists: assert mock_logger.error.called +class Test_Repository_GraphQL: + def setup_method(self): + self.mock_repo1 = MagicMock() + self.mock_repo1.id = 1 + self.mock_repo1.name = "repo1" + self.mock_repo1.owner.login = "owner1" + self.mock_repo1.full_name = "owner1/repo1" + self.mock_repo1.default_branch = "main" + self.mock_repo1.private = False + self.mock_repo1.archived = False + self.mock_repo1.pushed_at = datetime.now(timezone.utc) + self.mock_repo1.delete_branch_on_merge = False + self.mock_repo1.security_and_analysis = None + self.mock_repo1.get_contents.side_effect = [None, None, None] + self.mock_repo1.get_branch.side_effect = Exception("404 Not Found") + self.mock_repo1.get_dependabot_alerts.side_effect = Exception("403 Forbidden") + + def test_no_scoping_uses_graphql(self): + """Test that no scoping triggers the GraphQL discovery method successfully""" + provider = set_mocked_github_provider() + provider.repositories = [] + provider.organizations = [] + + with patch.object(Repository, "__init__", lambda x, y: None): + repository_service = Repository(provider) + mock_client = MagicMock() + repository_service.clients = [mock_client] + repository_service.provider = provider + + with patch.object( + repository_service, + "_get_accessible_repos_graphql", + return_value=["owner1/repo1"], + ) as mock_graphql_call: + mock_client.get_repo.return_value = self.mock_repo1 + + repos = repository_service._list_repositories() + + assert len(repos) == 1 + assert 1 in repos + assert repos[1].name == "repo1" + + mock_graphql_call.assert_called_once() + mock_client.get_repo.assert_called_once_with("owner1/repo1") + + def test_graphql_call_api_error(self): + """Test that an error during the GraphQL call is handled gracefully""" + provider = set_mocked_github_provider() + provider.repositories = [] + provider.organizations = [] + + with patch.object(Repository, "__init__", lambda x, y: None): + repository_service = Repository(provider) + repository_service.clients = [MagicMock()] + repository_service.provider = provider + + with patch( + "requests.post", + side_effect=requests.exceptions.RequestException("API Error"), + ): + with patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger: + + repos = repository_service._list_repositories() + + assert len(repos) == 0 + mock_logger.error.assert_called_once() + + log_output = str(mock_logger.error.call_args) + assert "RequestException" in log_output + assert "API Error" in log_output + + def test_graphql_returns_empty_list(self): + """Test the case where GraphQL returns no repositories""" + provider = set_mocked_github_provider() + provider.repositories = [] + provider.organizations = [] + + with patch.object(Repository, "__init__", lambda x, y: None): + repository_service = Repository(provider) + repository_service.clients = [MagicMock()] + repository_service.provider = provider + + with patch.object( + repository_service, "_get_accessible_repos_graphql", return_value=[] + ): + with patch( + "prowler.providers.github.services.repository.repository_service.logger" + ) as mock_logger: + + repos = repository_service._list_repositories() + + assert len(repos) == 0 + mock_logger.warning.assert_called_with( + "Could not find any accessible repositories with the provided token." + ) + + class Test_Repository_Scoping: def setup_method(self): self.mock_repo1 = MagicMock() @@ -123,7 +224,7 @@ class Test_Repository_Scoping: self.mock_repo1.pushed_at = datetime.now(timezone.utc) self.mock_repo1.delete_branch_on_merge = True self.mock_repo1.security_and_analysis = None - self.mock_repo1.get_contents.return_value = None + self.mock_repo1.get_contents.side_effect = [None, None, None] self.mock_repo1.get_branch.side_effect = Exception("404 Not Found") self.mock_repo1.get_dependabot_alerts.side_effect = Exception("404 Not Found") @@ -138,200 +239,10 @@ class Test_Repository_Scoping: self.mock_repo2.pushed_at = datetime.now(timezone.utc) self.mock_repo2.delete_branch_on_merge = True self.mock_repo2.security_and_analysis = None - self.mock_repo2.get_contents.return_value = None + self.mock_repo2.get_contents.side_effect = [None, None, None] self.mock_repo2.get_branch.side_effect = Exception("404 Not Found") self.mock_repo2.get_dependabot_alerts.side_effect = Exception("404 Not Found") - def test_no_repository_scoping(self): - """Test that all repositories are returned when no scoping is specified""" - provider = set_mocked_github_provider() - provider.repositories = [] - provider.organizations = [] - - mock_client = MagicMock() - mock_user = MagicMock() - mock_user.get_repos.return_value = [self.mock_repo1, self.mock_repo2] - mock_client.get_user.return_value = mock_user - - with patch( - "prowler.providers.github.services.repository.repository_service.GithubService.__init__" - ): - repository_service = Repository(provider) - repository_service.clients = [mock_client] - repository_service.provider = provider - - repos = repository_service._list_repositories() - - assert len(repos) == 2 - assert 1 in repos - assert 2 in repos - assert repos[1].name == "repo1" - assert repos[2].name == "repo2" - - def test_specific_repository_scoping(self): - """Test that only specified repositories are returned""" - provider = set_mocked_github_provider() - provider.repositories = ["owner1/repo1"] - provider.organizations = [] - - mock_client = MagicMock() - mock_client.get_repo.return_value = self.mock_repo1 - - with patch( - "prowler.providers.github.services.repository.repository_service.GithubService.__init__" - ): - repository_service = Repository(provider) - repository_service.clients = [mock_client] - repository_service.provider = provider - - repos = repository_service._list_repositories() - - assert len(repos) == 1 - assert 1 in repos - assert repos[1].name == "repo1" - assert repos[1].full_name == "owner1/repo1" - mock_client.get_repo.assert_called_once_with("owner1/repo1") - - def test_multiple_repository_scoping(self): - """Test that multiple specified repositories are returned""" - provider = set_mocked_github_provider() - provider.repositories = ["owner1/repo1", "owner2/repo2"] - provider.organizations = [] - - mock_client = MagicMock() - mock_client.get_repo.side_effect = [self.mock_repo1, self.mock_repo2] - - with patch( - "prowler.providers.github.services.repository.repository_service.GithubService.__init__" - ): - repository_service = Repository(provider) - repository_service.clients = [mock_client] - repository_service.provider = provider - - repos = repository_service._list_repositories() - - assert len(repos) == 2 - assert 1 in repos - assert 2 in repos - assert repos[1].name == "repo1" - assert repos[2].name == "repo2" - assert mock_client.get_repo.call_count == 2 - - def test_invalid_repository_format(self): - """Test that invalid repository formats are skipped with warning""" - provider = set_mocked_github_provider() - provider.repositories = ["invalid-repo-name", "owner/valid-repo"] - provider.organizations = [] - - mock_client = MagicMock() - mock_client.get_repo.return_value = self.mock_repo1 - - with patch( - "prowler.providers.github.services.repository.repository_service.GithubService.__init__" - ): - repository_service = Repository(provider) - repository_service.clients = [mock_client] - repository_service.provider = provider - - with patch( - "prowler.providers.github.services.repository.repository_service.logger" - ) as mock_logger: - repos = repository_service._list_repositories() - - # Should only have the valid repository - assert len(repos) == 1 - assert 1 in repos - # Should log warning for invalid format - assert mock_logger.warning.call_count >= 1 - # Check that at least one warning is about invalid format - warning_calls = [ - call[0][0] for call in mock_logger.warning.call_args_list - ] - assert any( - "should be in 'owner/repo-name' format" in call - for call in warning_calls - ) - - def test_repository_not_found(self): - """Test that inaccessible repositories are skipped with warning""" - provider = set_mocked_github_provider() - provider.repositories = ["owner/nonexistent-repo"] - provider.organizations = [] - - mock_client = MagicMock() - mock_client.get_repo.side_effect = Exception("404 Not Found") - - with patch( - "prowler.providers.github.services.repository.repository_service.GithubService.__init__" - ): - repository_service = Repository(provider) - repository_service.clients = [mock_client] - repository_service.provider = provider - - repos = repository_service._list_repositories() - - # Should be empty since repository wasn't found - assert len(repos) == 0 - - def test_organization_scoping(self): - """Test that repositories from specified organizations are returned""" - provider = set_mocked_github_provider() - provider.repositories = [] - provider.organizations = ["org1"] - - mock_client = MagicMock() - mock_org = MagicMock() - mock_org.get_repos.return_value = [self.mock_repo1] - mock_client.get_organization.return_value = mock_org - - with patch( - "prowler.providers.github.services.repository.repository_service.GithubService.__init__" - ): - repository_service = Repository(provider) - repository_service.clients = [mock_client] - repository_service.provider = provider - - repos = repository_service._list_repositories() - - assert len(repos) == 1 - assert 1 in repos - assert repos[1].name == "repo1" - mock_client.get_organization.assert_called_once_with("org1") - - def test_organization_as_user_fallback(self): - """Test that organization scoping falls back to user when organization not found""" - provider = set_mocked_github_provider() - provider.repositories = [] - provider.organizations = ["user1"] - - mock_client = MagicMock() - # Organization lookup fails - mock_client.get_organization.side_effect = GithubException( - 404, "Not Found", None - ) - # User lookup succeeds - mock_user = MagicMock() - mock_user.get_repos.return_value = [self.mock_repo1] - mock_client.get_user.return_value = mock_user - - # Create service without calling the parent constructor - repository_service = Repository.__new__(Repository) - repository_service.clients = [mock_client] - repository_service.provider = provider - - with patch( - "prowler.providers.github.services.repository.repository_service.logger" - ) as mock_logger: - repos = repository_service._list_repositories() - - assert len(repos) == 1 - assert 1 in repos - assert repos[1].name == "repo1" - mock_client.get_organization.assert_called_once_with("user1") - mock_client.get_user.assert_called_once_with("user1") - # Should log info about trying as user - mock_logger.info.assert_called() - def test_combined_repository_and_organization_scoping(self): """Test that both repository and organization scoping can be used together""" provider = set_mocked_github_provider() From 39e4d20b24b2b7150da7b29e75cce77c14fe046f Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Fri, 15 Aug 2025 13:25:15 +0200 Subject: [PATCH 20/30] feat(iam): add Bedrock AgentCore privilege escalation combo (#8526) --- prowler/CHANGELOG.md | 1 + .../services/iam/lib/privilege_escalation.py | 6 ++ ...policy_allows_privilege_escalation_test.py | 72 +++++++++++++++++++ ...policy_allows_privilege_escalation_test.py | 65 +++++++++++++++++ 4 files changed, 144 insertions(+) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 3161f5cd2f..e05172e495 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - Certificate authentication for M365 provider [(#8404)](https://github.com/prowler-cloud/prowler/pull/8404) - `vm_sufficient_daily_backup_retention_period` check for Azure provider [(#8200)](https://github.com/prowler-cloud/prowler/pull/8200) - `vm_jit_access_enabled` check for Azure provider [(#8202)](https://github.com/prowler-cloud/prowler/pull/8202) +- Bedrock AgentCore privilege escalation combination for AWS provider [(#8526)](https://github.com/prowler-cloud/prowler/pull/8526) ### Changed - Refine kisa isms-p compliance mapping [(#8479)](https://github.com/prowler-cloud/prowler/pull/8479) diff --git a/prowler/providers/aws/services/iam/lib/privilege_escalation.py b/prowler/providers/aws/services/iam/lib/privilege_escalation.py index 76245ce2c9..a9541f9d48 100644 --- a/prowler/providers/aws/services/iam/lib/privilege_escalation.py +++ b/prowler/providers/aws/services/iam/lib/privilege_escalation.py @@ -86,6 +86,12 @@ privilege_escalation_policies_combination = { "sts:AssumeRole", "iam:UpdateAssumeRolePolicy", }, + # AgentCore privilege escalation patterns + "PassRole+AgentCoreCreateInterpreter+InvokeInterpreter": { + "iam:PassRole", + "bedrock-agentcore:CreateCodeInterpreter", + "bedrock-agentcore:InvokeCodeInterpreter", + }, # TO-DO: We have to handle AssumeRole just if the resource is * and without conditions # "sts:AssumeRole": {"sts:AssumeRole"}, } diff --git a/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py b/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py index 2463dbd34f..84f697c39e 100644 --- a/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py +++ b/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py @@ -1219,3 +1219,75 @@ class Test_iam_inline_policy_allows_privilege_escalation: f"Inline Policy '{policy_name}' attached to role {role_arn} allows privilege escalation using the following actions:", finding.status_extended, ) + + @mock_aws + def test_iam_inline_role_policy_allows_privilege_escalation_agentcore(self): + """Test detection of AWS Bedrock AgentCore privilege escalation in inline role policy.""" + iam_client = client("iam", region_name=AWS_REGION_US_EAST_1) + # Create IAM Role + role_name = "agentcore_test_role" + role_arn = iam_client.create_role( + RoleName=role_name, + AssumeRolePolicyDocument=dumps(ADMINISTRATOR_ROLE_ASSUME_ROLE_POLICY), + )["Role"]["Arn"] + + # Put Role Policy with AgentCore privilege escalation permissions + policy_name = "agentcore_policy" + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "iam:PassRole", + "bedrock-agentcore:CreateCodeInterpreter", + "bedrock-agentcore:InvokeCodeInterpreter", + ], + "Resource": "*", + } + ], + } + _ = iam_client.put_role_policy( + RoleName=role_name, + PolicyName=policy_name, + PolicyDocument=dumps(policy_document), + ) + + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + from prowler.providers.aws.services.iam.iam_service import IAM + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch( + "prowler.providers.aws.services.iam.iam_inline_policy_allows_privilege_escalation.iam_inline_policy_allows_privilege_escalation.iam_client", + new=IAM(aws_provider), + ), + ): + # Test Check + from prowler.providers.aws.services.iam.iam_inline_policy_allows_privilege_escalation.iam_inline_policy_allows_privilege_escalation import ( + iam_inline_policy_allows_privilege_escalation, + ) + + check = iam_inline_policy_allows_privilege_escalation() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].resource_id == f"{role_name}/{policy_name}" + assert result[0].resource_arn == role_arn + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] + + assert search( + f"Inline policy {policy_name} attached to role {role_name} allows privilege escalation using the following actions: ", + result[0].status_extended, + ) + assert search("iam:PassRole", result[0].status_extended) + assert search( + "bedrock-agentcore:CreateCodeInterpreter", result[0].status_extended + ) + assert search( + "bedrock-agentcore:InvokeCodeInterpreter", result[0].status_extended + ) diff --git a/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py b/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py index d1a636a009..94f397d04b 100644 --- a/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py +++ b/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py @@ -915,6 +915,71 @@ class Test_iam_policy_allows_privilege_escalation: ]: assert search(permission, finding.status_extended) + @mock_aws + def test_iam_policy_allows_privilege_escalation_agentcore_passrole_create_invoke( + self, + ): + """Test detection of AWS Bedrock AgentCore privilege escalation pattern.""" + aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1]) + iam_client = client("iam", region_name=AWS_REGION_US_EAST_1) + policy_name = "agentcore_privilege_escalation_policy" + policy_document = { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "iam:PassRole", + "bedrock-agentcore:CreateCodeInterpreter", + "bedrock-agentcore:InvokeCodeInterpreter", + ], + "Resource": "*", + } + ], + } + + policy_arn = iam_client.create_policy( + PolicyName=policy_name, PolicyDocument=dumps(policy_document) + )["Policy"]["Arn"] + + from prowler.providers.aws.services.iam.iam_service import IAM + + with ( + mock.patch( + "prowler.providers.common.provider.Provider.get_global_provider", + return_value=aws_provider, + ), + mock.patch( + "prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client", + new=IAM(aws_provider), + ), + ): + # Test Check + from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import ( + iam_policy_allows_privilege_escalation, + ) + + check = iam_policy_allows_privilege_escalation() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].resource_id == policy_name + assert result[0].resource_arn == policy_arn + assert result[0].region == AWS_REGION_US_EAST_1 + assert result[0].resource_tags == [] + + assert search( + f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ", + result[0].status_extended, + ) + assert search("iam:PassRole", result[0].status_extended) + assert search( + "bedrock-agentcore:CreateCodeInterpreter", result[0].status_extended + ) + assert search( + "bedrock-agentcore:InvokeCodeInterpreter", result[0].status_extended + ) + @mock_aws def test_iam_policy_allows_privilege_escalation_iam_put( self, From fd833eecf07444225c7d0d36b43933226f4ad8d4 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Mon, 18 Aug 2025 02:35:19 -0400 Subject: [PATCH 21/30] fix(github): solve Github APP auth method (#8529) --- prowler/CHANGELOG.md | 9 +++++- prowler/providers/github/github_provider.py | 10 +++++- prowler/providers/github/models.py | 1 + .../services/repository/repository_service.py | 32 ++++++++++++++++++- tests/lib/outputs/finding_test.py | 4 ++- tests/lib/outputs/html/html_test.py | 2 +- .../providers/github/github_provider_test.py | 9 ++++-- 7 files changed, 60 insertions(+), 7 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index e05172e495..ce1114f587 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -17,7 +17,14 @@ All notable changes to the **Prowler SDK** are documented in this file. --- -## [v5.10.2] (Prowler UNRELEASED) +## [v5.10.3] (Prowler UNRELEASED) + +### Fixed +- GitHub App authentication for GitHub provider [(#8529)](https://github.com/prowler-cloud/prowler/pull/8529) + +--- + +## [v5.10.2] (Prowler v5.10.2) ### Fixed - Order requirements by ID in Prowler ThreatScore AWS compliance framework [(#8495)](https://github.com/prowler-cloud/prowler/pull/8495) diff --git a/prowler/providers/github/github_provider.py b/prowler/providers/github/github_provider.py index 4153b679da..5b86e9c76a 100644 --- a/prowler/providers/github/github_provider.py +++ b/prowler/providers/github/github_provider.py @@ -365,8 +365,16 @@ class GithubProvider(Provider): elif session.id != 0 and session.key: auth = Auth.AppAuth(session.id, session.key) gi = GithubIntegration(auth=auth, retry=retry_config) + installations = [] + for installation in gi.get_installations(): + installations.append( + installation.raw_data.get("account", {}).get("login") + ) try: - identity = GithubAppIdentityInfo(app_id=gi.get_app().id) + identity = GithubAppIdentityInfo( + app_id=gi.get_app().id, + installations=installations, + ) return identity except Exception as error: diff --git a/prowler/providers/github/models.py b/prowler/providers/github/models.py index b133dc9a69..bc1c382bc2 100644 --- a/prowler/providers/github/models.py +++ b/prowler/providers/github/models.py @@ -18,6 +18,7 @@ class GithubIdentityInfo(BaseModel): class GithubAppIdentityInfo(BaseModel): app_id: str + installations: list[str] class GithubOutputOptions(ProviderOutputOptions): diff --git a/prowler/providers/github/services/repository/repository_service.py b/prowler/providers/github/services/repository/repository_service.py index 674383a641..501bd72601 100644 --- a/prowler/providers/github/services/repository/repository_service.py +++ b/prowler/providers/github/services/repository/repository_service.py @@ -7,6 +7,7 @@ from pydantic.v1 import BaseModel from prowler.lib.logger import logger from prowler.providers.github.lib.service.service import GithubService +from prowler.providers.github.models import GithubAppIdentityInfo class Repository(GithubService): @@ -102,12 +103,23 @@ class Repository(GithubService): def _list_repositories(self): """ List repositories based on provider scoping configuration. + If the provider is a GitHub App, it will list repositories in the organizations that the GitHub App is installed in. + If the provider is a user, it will list repositories where the user is a member or owner. + If input repositories are provided, it will list repositories that match the input repositories. + If input organizations are provided, it will list repositories in the organizations that match the input organizations. """ logger.info("Repository - Listing Repositories...") repos = {} try: for client in self.clients: - if self.provider.repositories or self.provider.organizations: + if ( + self.provider.repositories + or self.provider.organizations + or ( + isinstance(self.provider.identity, GithubAppIdentityInfo) + and self.provider.identity.installations + ) + ): if self.provider.repositories: logger.info( f"Filtering for specific repositories: {self.provider.repositories}" @@ -141,6 +153,24 @@ class Repository(GithubService): self._handle_github_api_error( error, "processing organization", org_name ) + if ( + isinstance(self.provider.identity, GithubAppIdentityInfo) + and self.provider.identity.installations + ): + logger.info( + f"Filtering for repositories in the organizations or accounts that the GitHub App is installed in: {', '.join(self.provider.identity.installations)}" + ) + for org_name in self.provider.identity.installations: + try: + repos_list, _ = self._get_repositories_from_owner( + client, org_name + ) + for repo in repos_list: + self._process_repository(repo, repos) + except Exception as error: + self._handle_github_api_error( + error, "processing organization", org_name + ) else: logger.info( "No repository or organization specified, discovering accessible repositories via GraphQL API..." diff --git a/tests/lib/outputs/finding_test.py b/tests/lib/outputs/finding_test.py index 5b22fa675d..f9d4aaf7de 100644 --- a/tests/lib/outputs/finding_test.py +++ b/tests/lib/outputs/finding_test.py @@ -585,7 +585,9 @@ class TestFinding: provider = MagicMock() provider.type = "github" # GitHub App identity only has app_id, not account_name/account_id - provider.identity = GithubAppIdentityInfo(app_id=APP_ID) + provider.identity = GithubAppIdentityInfo( + app_id=APP_ID, installations=["test-org"] + ) provider.auth_method = "GitHub App Token" # Mock check result diff --git a/tests/lib/outputs/html/html_test.py b/tests/lib/outputs/html/html_test.py index e3a834e452..e85567b20a 100644 --- a/tests/lib/outputs/html/html_test.py +++ b/tests/lib/outputs/html/html_test.py @@ -673,7 +673,7 @@ class TestHTML: provider = set_mocked_github_provider( auth_method="GitHub App Token", - identity=GithubAppIdentityInfo(app_id=APP_ID), + identity=GithubAppIdentityInfo(app_id=APP_ID, installations=["test-org"]), ) summary = output.get_assessment_summary(provider) diff --git a/tests/providers/github/github_provider_test.py b/tests/providers/github/github_provider_test.py index a3c74bca86..199964a743 100644 --- a/tests/providers/github/github_provider_test.py +++ b/tests/providers/github/github_provider_test.py @@ -135,6 +135,7 @@ class TestGitHubProvider: "prowler.providers.github.github_provider.GithubProvider.setup_identity", return_value=GithubAppIdentityInfo( app_id=APP_ID, + installations=["test-org"], ), ), ): @@ -147,7 +148,9 @@ class TestGitHubProvider: assert provider._type == "github" assert provider.session == GithubSession(token="", id=APP_ID, key=APP_KEY) - assert provider.identity == GithubAppIdentityInfo(app_id=APP_ID) + assert provider.identity == GithubAppIdentityInfo( + app_id=APP_ID, installations=["test-org"] + ) assert provider._audit_config == { "inactive_not_archived_days_threshold": 180, } @@ -206,7 +209,9 @@ class TestGitHubProvider: ), patch( "prowler.providers.github.github_provider.GithubProvider.setup_identity", - return_value=GithubAppIdentityInfo(app_id=APP_ID), + return_value=GithubAppIdentityInfo( + app_id=APP_ID, installations=["test-org"] + ), ), ): connection = GithubProvider.test_connection( From 3aeaa3d99226abd58ed8cdda68e6275ab95028f3 Mon Sep 17 00:00:00 2001 From: Pablo Lara Date: Mon, 18 Aug 2025 09:10:16 +0200 Subject: [PATCH 22/30] feat(filters): improve provider connection filter UX (#8520) --- ui/CHANGELOG.md | 1 + ui/components/filters/data-filters.ts | 8 +++--- .../ui/custom/custom-dropdown-filter.tsx | 12 ++++++--- ui/lib/helper-filters.ts | 27 +++++++++++++++++++ ui/types/filters.ts | 7 +++-- ui/types/providers.ts | 5 ++++ 6 files changed, 52 insertions(+), 8 deletions(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index f85ed7a8c8..5418639d0b 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to the **Prowler UI** are documented in this file. ### 🔄 Changed - Disable `See Compliance` button until scan completes [(#8487)](https://github.com/prowler-cloud/prowler/pull/8487) +- Provider connection filter now shows "Connected/Disconnected" instead of "true/false" for better UX [(#8520)](https://github.com/prowler-cloud/prowler/pull/8520) ### 🐞 Fixed - DataTable column headers set to single-line [(#8480)](https://github.com/prowler-cloud/prowler/pull/8480) diff --git a/ui/components/filters/data-filters.ts b/ui/components/filters/data-filters.ts index 489e23bb54..6bcbd40161 100644 --- a/ui/components/filters/data-filters.ts +++ b/ui/components/filters/data-filters.ts @@ -1,11 +1,13 @@ -import { FilterType } from "@/types/filters"; +import { CONNECTION_STATUS_MAPPING } from "@/lib/helper-filters"; +import { FilterOption, FilterType } from "@/types/filters"; import { PROVIDER_TYPES } from "@/types/providers"; -export const filterProviders = [ +export const filterProviders: FilterOption[] = [ { key: "connected", labelCheckboxGroup: "Connection", - values: ["false", "true"], + values: ["true", "false"], + valueLabelMapping: CONNECTION_STATUS_MAPPING, }, { key: "provider__in", diff --git a/ui/components/ui/custom/custom-dropdown-filter.tsx b/ui/components/ui/custom/custom-dropdown-filter.tsx index 30bfea3a29..50a80f3349 100644 --- a/ui/components/ui/custom/custom-dropdown-filter.tsx +++ b/ui/components/ui/custom/custom-dropdown-filter.tsx @@ -22,7 +22,7 @@ import React, { import { ComplianceScanInfo } from "@/components/compliance/compliance-header/compliance-scan-info"; import { EntityInfoShort } from "@/components/ui/entities"; -import { isScanEntity } from "@/lib/helper-filters"; +import { isConnectionStatus, isScanEntity } from "@/lib/helper-filters"; import { CustomDropdownFilterProps, FilterEntity, @@ -189,6 +189,10 @@ export const CustomDropdownFilter = ({ )?.[value]; if (!entity) return value; + if (isConnectionStatus(entity)) { + return entity.label; + } + if (isScanEntity(entity as ScanEntity)) { return ( (entity as ScanEntity).attributes?.name || @@ -320,7 +324,9 @@ export const CustomDropdownFilter = ({ value={value} > {entity ? ( - isScanEntity(entity as ScanEntity) ? ( + isConnectionStatus(entity) ? ( + getDisplayLabel(value) + ) : isScanEntity(entity as ScanEntity) ? ( ) : ( ) ) : ( - value + getDisplayLabel(value) )} ); diff --git a/ui/lib/helper-filters.ts b/ui/lib/helper-filters.ts index 15ac934c29..6598baf33c 100644 --- a/ui/lib/helper-filters.ts +++ b/ui/lib/helper-filters.ts @@ -1,4 +1,6 @@ import { ProviderProps, ProvidersApiResponse, ScanProps } from "@/types"; +import { FilterEntity } from "@/types/filters"; +import { ProviderConnectionStatus } from "@/types/providers"; import { ScanEntity } from "@/types/scans"; /** @@ -125,3 +127,28 @@ export const createScanDetailsMapping = ( return scanMappings; }; + +// Helper to check if entity is a ProviderConnectionStatus (simple label/value object) +export const isConnectionStatus = ( + entity: FilterEntity, +): entity is ProviderConnectionStatus => { + return !!(entity && "label" in entity && "value" in entity); +}; + +/** + * Connection status mapping for provider filters. + * Maps boolean string values to user-friendly labels. + */ +export const CONNECTION_STATUS_MAPPING: Array<{ + [key: string]: FilterEntity; +}> = [ + { + true: { label: "Connected", value: "true" } as ProviderConnectionStatus, + }, + { + false: { + label: "Disconnected", + value: "false", + } as ProviderConnectionStatus, + }, +]; diff --git a/ui/types/filters.ts b/ui/types/filters.ts index 911a67651c..7f7986d6e6 100644 --- a/ui/types/filters.ts +++ b/ui/types/filters.ts @@ -1,7 +1,10 @@ -import { ProviderEntity } from "./providers"; +import { ProviderConnectionStatus, ProviderEntity } from "./providers"; import { ScanEntity } from "./scans"; -export type FilterEntity = ProviderEntity | ScanEntity; +export type FilterEntity = + | ProviderEntity + | ScanEntity + | ProviderConnectionStatus; export interface FilterOption { key: string; diff --git a/ui/types/providers.ts b/ui/types/providers.ts index 0967d3304e..86f4e90533 100644 --- a/ui/types/providers.ts +++ b/ui/types/providers.ts @@ -60,6 +60,11 @@ export interface ProviderEntity { alias: string | null; } +export interface ProviderConnectionStatus { + label: string; + value: string; +} + export interface ProviderOverviewProps { data: { type: "provider-overviews"; From 6918a7544900a08d0b47271d75c7b3705376e770 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah Date: Mon, 18 Aug 2025 13:19:23 +0530 Subject: [PATCH 23/30] fix: add business context to lighthouse chat (#8528) Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> --- ui/app/api/lighthouse/analyst/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/app/api/lighthouse/analyst/route.ts b/ui/app/api/lighthouse/analyst/route.ts index 435f063c35..51cf2bec4f 100644 --- a/ui/app/api/lighthouse/analyst/route.ts +++ b/ui/app/api/lighthouse/analyst/route.ts @@ -26,7 +26,7 @@ export async function POST(req: Request) { // Get AI configuration to access business context const aiConfig = await getLighthouseConfig(); - const businessContext = aiConfig?.data?.attributes?.business_context; + const businessContext = aiConfig?.attributes?.business_context; // Get current user data const currentData = await getCurrentDataSection(); From 2f5fce41dc283a96b714f112333ec32444a3f629 Mon Sep 17 00:00:00 2001 From: Andoni Alonso <14891798+andoniaf@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:35:14 +0200 Subject: [PATCH 24/30] feat(iam): remove standalone iam:PassRole from privesc detection and add missing patterns (#8530) --- prowler/CHANGELOG.md | 1 + .../aws/services/iam/lib/privilege_escalation.py | 16 +++++++++++++++- ...ne_policy_allows_privilege_escalation_test.py | 10 ++++------ ...am_policy_allows_privilege_escalation_test.py | 15 ++++++--------- .../iam/lib/privilege_escalation_test.py | 13 +++++++------ 5 files changed, 33 insertions(+), 22 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index ce1114f587..5395f0e767 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - `vm_sufficient_daily_backup_retention_period` check for Azure provider [(#8200)](https://github.com/prowler-cloud/prowler/pull/8200) - `vm_jit_access_enabled` check for Azure provider [(#8202)](https://github.com/prowler-cloud/prowler/pull/8202) - Bedrock AgentCore privilege escalation combination for AWS provider [(#8526)](https://github.com/prowler-cloud/prowler/pull/8526) +- Remove standalone iam:PassRole from privesc detection and add missing patterns [(#8530)](https://github.com/prowler-cloud/prowler/pull/8530) ### Changed - Refine kisa isms-p compliance mapping [(#8479)](https://github.com/prowler-cloud/prowler/pull/8479) diff --git a/prowler/providers/aws/services/iam/lib/privilege_escalation.py b/prowler/providers/aws/services/iam/lib/privilege_escalation.py index a9541f9d48..9a4a67d3ab 100644 --- a/prowler/providers/aws/services/iam/lib/privilege_escalation.py +++ b/prowler/providers/aws/services/iam/lib/privilege_escalation.py @@ -24,7 +24,6 @@ privilege_escalation_policies_combination = { "IAMPut": {"iam:Put*"}, "CreatePolicyVersion": {"iam:CreatePolicyVersion"}, "SetDefaultPolicyVersion": {"iam:SetDefaultPolicyVersion"}, - "iam:PassRole": {"iam:PassRole"}, "PassRole+EC2": { "iam:PassRole", "ec2:RunInstances", @@ -69,6 +68,21 @@ privilege_escalation_policies_combination = { }, "GlueUpdateDevEndpoint": {"glue:UpdateDevEndpoint"}, "lambda:UpdateFunctionCode": {"lambda:UpdateFunctionCode"}, + "lambda:UpdateFunctionConfiguration": {"lambda:UpdateFunctionConfiguration"}, + "PassRole+CodeStar": { + "iam:PassRole", + "codestar:CreateProject", + }, + "PassRole+CreateAutoScaling": { + "iam:PassRole", + "autoscaling:CreateAutoScalingGroup", + "autoscaling:CreateLaunchConfiguration", + }, + "PassRole+UpdateAutoScaling": { + "iam:PassRole", + "autoscaling:UpdateAutoScalingGroup", + "autoscaling:CreateLaunchConfiguration", + }, "iam:CreateAccessKey": {"iam:CreateAccessKey"}, "iam:CreateLoginProfile": {"iam:CreateLoginProfile"}, "iam:UpdateLoginProfile": {"iam:UpdateLoginProfile"}, diff --git a/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py b/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py index 84f697c39e..176942ea0b 100644 --- a/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py +++ b/tests/providers/aws/services/iam/iam_inline_policy_allows_privilege_escalation/iam_inline_policy_allows_privilege_escalation_test.py @@ -362,17 +362,16 @@ class Test_iam_inline_policy_allows_privilege_escalation: check = iam_inline_policy_allows_privilege_escalation() result = check.execute() assert len(result) == 1 - assert result[0].status == "FAIL" + assert result[0].status == "PASS" assert result[0].resource_id == f"test_role/{policy_name}" assert result[0].resource_arn == role_arn assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] assert search( - f"Inline policy {policy_name} attached to role {role_name} allows privilege escalation using the following actions: ", + f"Inline policy {policy_name} attached to role {role_name} does not allow privilege escalation", result[0].status_extended, ) - assert search("iam:PassRole", result[0].status_extended) @mock_aws def test_iam_inline_policy_allows_privilege_escalation_two_combinations( @@ -511,17 +510,16 @@ class Test_iam_inline_policy_allows_privilege_escalation: check = iam_inline_policy_allows_privilege_escalation() result = check.execute() assert len(result) == 1 - assert result[0].status == "FAIL" + assert result[0].status == "PASS" assert result[0].resource_id == f"test_role/{policy_name}" assert result[0].resource_arn == role_arn assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] assert search( - f"Inline policy {policy_name} attached to role {role_name} allows privilege escalation using the following actions: ", + f"Inline policy {policy_name} attached to role {role_name} does not allow privilege escalation", result[0].status_extended, ) - assert search("iam:PassRole", result[0].status_extended) @mock_aws def test_iam_inline_policy_allows_privilege_escalation_policies_combination( diff --git a/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py b/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py index 94f397d04b..79e1b25955 100644 --- a/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py +++ b/tests/providers/aws/services/iam/iam_policy_allows_privilege_escalation/iam_policy_allows_privilege_escalation_test.py @@ -322,17 +322,16 @@ class Test_iam_policy_allows_privilege_escalation: check = iam_policy_allows_privilege_escalation() result = check.execute() assert len(result) == 1 - assert result[0].status == "FAIL" + assert result[0].status == "PASS" assert result[0].resource_id == policy_name assert result[0].resource_arn == policy_arn assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] assert search( - f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ", + f"Custom Policy {policy_arn} does not allow privilege escalation", result[0].status_extended, ) - assert search("iam:PassRole", result[0].status_extended) @mock_aws def test_iam_policy_allows_privilege_escalation_iam_PassRole_using_wildcard( @@ -375,17 +374,16 @@ class Test_iam_policy_allows_privilege_escalation: check = iam_policy_allows_privilege_escalation() result = check.execute() assert len(result) == 1 - assert result[0].status == "FAIL" + assert result[0].status == "PASS" assert result[0].resource_id == policy_name assert result[0].resource_arn == policy_arn assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] assert search( - f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ", + f"Custom Policy {policy_arn} does not allow privilege escalation", result[0].status_extended, ) - assert search("iam:PassRole", result[0].status_extended) @mock_aws def test_iam_policy_allows_privilege_escalation_two_combinations( @@ -508,17 +506,16 @@ class Test_iam_policy_allows_privilege_escalation: check = iam_policy_allows_privilege_escalation() result = check.execute() assert len(result) == 1 - assert result[0].status == "FAIL" + assert result[0].status == "PASS" assert result[0].resource_id == policy_name assert result[0].resource_arn == policy_arn assert result[0].region == AWS_REGION_US_EAST_1 assert result[0].resource_tags == [] assert search( - f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ", + f"Custom Policy {policy_arn} does not allow privilege escalation", result[0].status_extended, ) - assert search("iam:PassRole", result[0].status_extended) @mock_aws def test_iam_policy_allows_privilege_escalation_policies_combination( diff --git a/tests/providers/aws/services/iam/lib/privilege_escalation_test.py b/tests/providers/aws/services/iam/lib/privilege_escalation_test.py index 3b3123709f..018af5e1ec 100644 --- a/tests/providers/aws/services/iam/lib/privilege_escalation_test.py +++ b/tests/providers/aws/services/iam/lib/privilege_escalation_test.py @@ -52,7 +52,6 @@ class Test_PrivilegeEscalation: assert "iam:Put*" in result assert "iam:AddUserToGroup" in result assert "iam:AttachRolePolicy" in result - assert "iam:PassRole" in result assert "iam:CreateLoginProfile" in result assert "iam:CreateAccessKey" in result assert "iam:AttachGroupPolicy" in result @@ -78,9 +77,9 @@ class Test_PrivilegeEscalation: ], } result = check_privilege_escalation(policy) - assert "iam:PassRole" in result + assert result == "" - def test_check_privilege_escalation_priv_escalation_iam_PassRole_using_wildcard( + def test_check_privilege_escalation_priv_escalation_iam_wildcard( self, ): policy = { @@ -88,13 +87,16 @@ class Test_PrivilegeEscalation: "Statement": [ { "Effect": "Allow", - "Action": ["iam:*Role"], # Should expand to include PassRole + "Action": [ + "iam:*" + ], # Should expand to include multiple IAM actions "Resource": ["*"], } ], } result = check_privilege_escalation(policy) - assert "iam:PassRole" in result + # iam:* should expand to include PutUserPolicy and other privilege escalation actions + assert "iam:PutUserPolicy" in result def test_check_privilege_escalation_priv_escalation_not_action( self, @@ -117,7 +119,6 @@ class Test_PrivilegeEscalation: assert "'iam:PutGroupPolicy'" not in result assert "iam:AddUserToGroup" in result assert "iam:AttachRolePolicy" in result - assert "iam:PassRole" in result assert "iam:CreateLoginProfile" in result assert "iam:CreateAccessKey" in result assert "iam:AttachGroupPolicy" in result From d57df3cc28282ecab57428645cea5bc67eeff8f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 18 Aug 2025 11:43:41 +0200 Subject: [PATCH 25/30] chore(deps): bump actions/upload-artifact from 4.5.0 to 4.6.2 (#8154) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ui-e2e-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ui-e2e-tests.yml b/.github/workflows/ui-e2e-tests.yml index e13ec2482a..543857a511 100644 --- a/.github/workflows/ui-e2e-tests.yml +++ b/.github/workflows/ui-e2e-tests.yml @@ -84,7 +84,7 @@ jobs: working-directory: ./ui run: npm run test:e2e - name: Upload test reports - uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 if: failure() with: name: playwright-report From 9214b5c26fefe26ea6f771c47ad657986e8bf1c8 Mon Sep 17 00:00:00 2001 From: Prowler Bot Date: Mon, 18 Aug 2025 11:58:41 +0200 Subject: [PATCH 26/30] chore(regions_update): Changes in regions for AWS services (#8531) Co-authored-by: prowler-bot <179230569+prowler-bot@users.noreply.github.com> --- prowler/providers/aws/aws_regions_by_service.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/prowler/providers/aws/aws_regions_by_service.json b/prowler/providers/aws/aws_regions_by_service.json index 416d2ef8d5..7943a1078f 100644 --- a/prowler/providers/aws/aws_regions_by_service.json +++ b/prowler/providers/aws/aws_regions_by_service.json @@ -1430,7 +1430,9 @@ "us-west-2" ], "aws-cn": [], - "aws-us-gov": [] + "aws-us-gov": [ + "us-gov-west-1" + ] } }, "bedrock-runtime": { @@ -8270,6 +8272,7 @@ "aws": [ "af-south-1", "ap-east-1", + "ap-east-2", "ap-northeast-1", "ap-northeast-2", "ap-northeast-3", From bb07cf9147cde9b911273dc1b5518d28f677a992 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Mon, 18 Aug 2025 12:11:13 +0200 Subject: [PATCH 27/30] fix(aws): exact match in resource-arn filtering (#8533) --- prowler/CHANGELOG.md | 1 + prowler/lib/scan_filters/scan_filters.py | 2 +- tests/lib/scan_filters/scan_filters_test.py | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 5395f0e767..577895b884 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file. ## [v5.10.3] (Prowler UNRELEASED) ### Fixed +- AWS resource-arn filtering [(#8533)](https://github.com/prowler-cloud/prowler/pull/8533) - GitHub App authentication for GitHub provider [(#8529)](https://github.com/prowler-cloud/prowler/pull/8529) --- diff --git a/prowler/lib/scan_filters/scan_filters.py b/prowler/lib/scan_filters/scan_filters.py index 6f93907fea..4801934370 100644 --- a/prowler/lib/scan_filters/scan_filters.py +++ b/prowler/lib/scan_filters/scan_filters.py @@ -8,7 +8,7 @@ def is_resource_filtered(resource: str, audit_resources: list) -> bool: Returns True if it is filtered and False if it does not match the input filters """ try: - if resource in str(audit_resources): + if resource in audit_resources: return True return False except Exception as error: diff --git a/tests/lib/scan_filters/scan_filters_test.py b/tests/lib/scan_filters/scan_filters_test.py index 5c71c21e1f..94daa96dba 100644 --- a/tests/lib/scan_filters/scan_filters_test.py +++ b/tests/lib/scan_filters/scan_filters_test.py @@ -13,5 +13,4 @@ class Test_Scan_Filters: assert not is_resource_filtered( "arn:aws:iam::123456789012:user/test1", audit_resources ) - assert is_resource_filtered("test_bucket", audit_resources) assert is_resource_filtered("arn:aws:s3:::test_bucket", audit_resources) From efdeb431ba6007b75278e27d4367c607ab7b2fe1 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah Date: Tue, 19 Aug 2025 13:10:14 +0530 Subject: [PATCH 28/30] feat: Add resource agent to supervisor (#8509) Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> --- ui/CHANGELOG.md | 3 +- ui/actions/lighthouse/resources.ts | 88 ++++++++++++++++++++++++---- ui/lib/lighthouse/prompts.ts | 33 +++++++++++ ui/lib/lighthouse/tools/resources.ts | 29 +++++++-- ui/lib/lighthouse/workflow.ts | 14 +++++ ui/types/lighthouse/resources.ts | 14 +++-- 6 files changed, 157 insertions(+), 24 deletions(-) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 5418639d0b..6e5521eb28 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the **Prowler UI** are documented in this file. - `Cloud Provider` type filter to providers page [(#8473)](https://github.com/prowler-cloud/prowler/pull/8473) - New menu item under Configuration section for quick access to the Mutelist [(#8444)](https://github.com/prowler-cloud/prowler/pull/8444) +- Resource agent to Lighthouse for querying resource information [(#8509)](https://github.com/prowler-cloud/prowler/pull/8509) ### 🔄 Changed @@ -15,6 +16,7 @@ All notable changes to the **Prowler UI** are documented in this file. - Provider connection filter now shows "Connected/Disconnected" instead of "true/false" for better UX [(#8520)](https://github.com/prowler-cloud/prowler/pull/8520) ### 🐞 Fixed + - DataTable column headers set to single-line [(#8480)](https://github.com/prowler-cloud/prowler/pull/8480) ### ❌ Removed @@ -29,7 +31,6 @@ All notable changes to the **Prowler UI** are documented in this file. - `GitHub` submenu to High Risk Findings [(#8488)](https://github.com/prowler-cloud/prowler/pull/8488) - Improved Overview chart `Findings by Severity` spacing [(#8491)](https://github.com/prowler-cloud/prowler/pull/8491) - ## [1.10.0] (Prowler v5.10.0) ### 🚀 Added diff --git a/ui/actions/lighthouse/resources.ts b/ui/actions/lighthouse/resources.ts index 21beaabc19..cf763909e0 100644 --- a/ui/actions/lighthouse/resources.ts +++ b/ui/actions/lighthouse/resources.ts @@ -1,12 +1,18 @@ import { apiBaseUrl, getAuthHeaders, parseStringify } from "@/lib/helper"; -export async function getLighthouseResources( - page: number = 1, - query: string = "", - sort: string = "", - filters: any = {}, - fields: string[] = [], -) { +export async function getLighthouseResources({ + page = 1, + query = "", + sort = "", + filters = {}, + fields = [], +}: { + page?: number; + query?: string; + sort?: string; + filters?: any; + fields?: string[]; +}) { const headers = await getAuthHeaders({ contentType: false }); const url = new URL(`${apiBaseUrl}/resources`); @@ -29,7 +35,7 @@ export async function getLighthouseResources( if (filters) { for (const [key, value] of Object.entries(filters)) { - url.searchParams.append(`filter[${key}]`, value as string); + url.searchParams.append(`${key}`, value as string); } } @@ -46,11 +52,67 @@ export async function getLighthouseResources( } } -export async function getLighthouseResourceById( - id: string, - fields: string[] = [], - include: string[] = [], -) { +export async function getLighthouseLatestResources({ + page = 1, + query = "", + sort = "", + filters = {}, + fields = [], +}: { + page?: number; + query?: string; + sort?: string; + filters?: any; + fields?: string[]; +}) { + const headers = await getAuthHeaders({ contentType: false }); + + const url = new URL(`${apiBaseUrl}/resources/latest`); + + if (page) { + url.searchParams.append("page[number]", page.toString()); + } + + if (sort) { + url.searchParams.append("sort", sort); + } + + if (query) { + url.searchParams.append("filter[search]", query); + } + + if (fields.length > 0) { + url.searchParams.append("fields[resources]", fields.join(",")); + } + + if (filters) { + for (const [key, value] of Object.entries(filters)) { + url.searchParams.append(`${key}`, value as string); + } + } + + try { + const response = await fetch(url.toString(), { + headers, + }); + const data = await response.json(); + const parsedData = parseStringify(data); + return parsedData; + } catch (error) { + console.error("Error fetching resources:", error); + return undefined; + } +} + +export async function getLighthouseResourceById({ + id, + fields = [], + include = [], +}: { + id: string; + fields?: string[]; + include?: string[]; +}) { const headers = await getAuthHeaders({ contentType: false }); const url = new URL(`${apiBaseUrl}/resources/${id}`); diff --git a/ui/lib/lighthouse/prompts.ts b/ui/lib/lighthouse/prompts.ts index 318ac1479d..5c5ddfd9d1 100644 --- a/ui/lib/lighthouse/prompts.ts +++ b/ui/lib/lighthouse/prompts.ts @@ -136,6 +136,11 @@ You operate in an agent loop, iterating through these steps: - Fetches available user roles in Prowler - Can get detailed information about the role +### resources_agent + +- Fetches information about resources found during Prowler scans +- Can get detailed information about a specific resource + ## Interacting with Agents - Don't invoke agents if you have the necessary information in your prompt. @@ -469,11 +474,39 @@ const rolesAgentPrompt = `You are Prowler's Roles Agent, specializing in role an - Mentioning all keys in the function call is mandatory. Don't skip any keys. - Don't add empty filters in the function call.`; +const resourcesAgentPrompt = `You are Prowler's Resource Agent, specializing in fetching resource information within Prowler. + +## Available Tools + +- getResourcesTool: List available resource with filtering options +- getResourceTool: Get detailed information about a specific resource by its UUID +- getLatestResourcesTool: List available resources from the latest scans across all providers without scan UUID + +## Response Guidelines + +- Keep the response concise +- Only share information relevant to the query +- Answer directly without unnecessary introductions or conclusions +- Ensure all responses are based on tools' output and information available in the prompt + +## Additional Guidelines + +- Focus only on resource-related information +- Format resource IDs, permissions, and descriptions consistently +- When user asks for resources without a specific scan UUID, use getLatestResourcesTool tool to fetch the resources +- To get the resource UUID, use getResourcesTool if scan UUID is present. If scan UUID is not present, use getLatestResourcesTool. + +## Tool Calling Guidelines + +- Mentioning all keys in the function call is mandatory. Don't skip any keys. +- Don't add empty filters in the function call.`; + export { complianceAgentPrompt, findingsAgentPrompt, overviewAgentPrompt, providerAgentPrompt, + resourcesAgentPrompt, rolesAgentPrompt, scansAgentPrompt, supervisorPrompt, diff --git a/ui/lib/lighthouse/tools/resources.ts b/ui/lib/lighthouse/tools/resources.ts index 62b0bcc2e6..408ad5fc6d 100644 --- a/ui/lib/lighthouse/tools/resources.ts +++ b/ui/lib/lighthouse/tools/resources.ts @@ -1,6 +1,7 @@ import { tool } from "@langchain/core/tools"; import { + getLighthouseLatestResources, getLighthouseResourceById, getLighthouseResources, } from "@/actions/lighthouse/resources"; @@ -8,22 +9,42 @@ import { getResourceSchema, getResourcesSchema } from "@/types/lighthouse"; export const getResourcesTool = tool( async ({ page, query, sort, filters, fields }) => { - return await getLighthouseResources(page, query, sort, filters, fields); + return await getLighthouseResources({ page, query, sort, filters, fields }); }, { name: "getResources", - description: "Fetches all resource information", + description: + "Retrieve a list of all resources found during scans with options for filtering by various criteria. Mandatory to pass in scan UUID.", schema: getResourcesSchema, }, ); export const getResourceTool = tool( async ({ id, fields, include }) => { - return await getLighthouseResourceById(id, fields, include); + return await getLighthouseResourceById({ id, fields, include }); }, { name: "getResource", - description: "Fetches information about a resource by its UUID.", + description: + "Fetch detailed information about a specific resource by their Prowler assigned UUID. A Resource is an object that is discovered by Prowler. It can be anything from a single host to a whole VPC.", schema: getResourceSchema, }, ); + +export const getLatestResourcesTool = tool( + async ({ page, query, sort, filters, fields }) => { + return await getLighthouseLatestResources({ + page, + query, + sort, + filters, + fields, + }); + }, + { + name: "getLatestResources", + description: + "Retrieve a list of the latest resources from the latest scans across all providers with options for filtering by various criteria.", + schema: getResourcesSchema, // Schema is same as getResourcesSchema + }, +); diff --git a/ui/lib/lighthouse/workflow.ts b/ui/lib/lighthouse/workflow.ts index faa7f02f4c..ff5996b95b 100644 --- a/ui/lib/lighthouse/workflow.ts +++ b/ui/lib/lighthouse/workflow.ts @@ -8,6 +8,7 @@ import { findingsAgentPrompt, overviewAgentPrompt, providerAgentPrompt, + resourcesAgentPrompt, rolesAgentPrompt, scansAgentPrompt, supervisorPrompt, @@ -35,6 +36,11 @@ import { getProvidersTool, getProviderTool, } from "@/lib/lighthouse/tools/providers"; +import { + getLatestResourcesTool, + getResourcesTool, + getResourceTool, +} from "@/lib/lighthouse/tools/resources"; import { getRolesTool, getRoleTool } from "@/lib/lighthouse/tools/roles"; import { getScansTool, getScanTool } from "@/lib/lighthouse/tools/scans"; import { @@ -127,6 +133,13 @@ export async function initLighthouseWorkflow() { prompt: rolesAgentPrompt, }); + const resourcesAgent = createReactAgent({ + llm: llm, + tools: [getResourceTool, getResourcesTool, getLatestResourcesTool], + name: "resources_agent", + prompt: resourcesAgentPrompt, + }); + const agents = [ userInfoAgent, providerAgent, @@ -135,6 +148,7 @@ export async function initLighthouseWorkflow() { complianceAgent, findingsAgent, rolesAgent, + resourcesAgent, ]; // Create supervisor workflow diff --git a/ui/types/lighthouse/resources.ts b/ui/types/lighthouse/resources.ts index 7b70dfe96b..354cbb89d0 100644 --- a/ui/types/lighthouse/resources.ts +++ b/ui/types/lighthouse/resources.ts @@ -11,6 +11,7 @@ const resourceFieldsEnum = z.enum([ "tags", "provider", "findings", + "failed_findings_count", "url", "type", ]); @@ -129,6 +130,10 @@ export const getResourcesSchema = z.object({ .optional() .describe("Filter by multiple tags separated by commas."), "filter[type]": z.string().optional().describe("Filter by type."), + "filter[type__icontains]": z + .string() + .optional() + .describe("Filter by substring."), "filter[type__in]": z .string() .optional() @@ -138,18 +143,15 @@ export const getResourcesSchema = z.object({ .string() .optional() .describe("Filter by substring."), - "filter[updated_at]": z - .string() - .optional() - .describe("The uid to filter by."), + "filter[updated_at]": z.string().optional().describe("Filter by date."), "filter[updated_at__gte]": z .string() .optional() - .describe("The uid to filter by."), + .describe("Filter by date greater than or equal to."), "filter[updated_at__lte]": z .string() .optional() - .describe("The uid to filter by."), + .describe("Filter by date less than or equal to."), }) .optional() .describe("The filters to apply to the resources."), From 30518f2e0e619269babca54e0ba6bbf7e27ed631 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 19 Aug 2025 10:25:24 +0200 Subject: [PATCH 29/30] feat(aws): new check `eks_cluster_deletion_protection_enabled` (#8536) --- prowler/CHANGELOG.md | 1 + .../__init__.py | 0 ..._deletion_protection_enabled.metadata.json | 32 +++++ ...eks_cluster_deletion_protection_enabled.py | 21 +++ .../providers/aws/services/eks/eks_service.py | 5 + ...luster_deletion_protection_enabled_test.py | 122 ++++++++++++++++++ 6 files changed, 181 insertions(+) create mode 100644 prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/__init__.py create mode 100644 prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json create mode 100644 prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.py create mode 100644 tests/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled_test.py diff --git a/prowler/CHANGELOG.md b/prowler/CHANGELOG.md index 577895b884..dec6f062ae 100644 --- a/prowler/CHANGELOG.md +++ b/prowler/CHANGELOG.md @@ -10,6 +10,7 @@ All notable changes to the **Prowler SDK** are documented in this file. - `vm_jit_access_enabled` check for Azure provider [(#8202)](https://github.com/prowler-cloud/prowler/pull/8202) - Bedrock AgentCore privilege escalation combination for AWS provider [(#8526)](https://github.com/prowler-cloud/prowler/pull/8526) - Remove standalone iam:PassRole from privesc detection and add missing patterns [(#8530)](https://github.com/prowler-cloud/prowler/pull/8530) +- `eks_cluster_deletion_protection_enabled` check for AWS provider [(#8536)](https://github.com/prowler-cloud/prowler/pull/8536) ### Changed - Refine kisa isms-p compliance mapping [(#8479)](https://github.com/prowler-cloud/prowler/pull/8479) diff --git a/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/__init__.py b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json new file mode 100644 index 0000000000..5a0ec82bb7 --- /dev/null +++ b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.metadata.json @@ -0,0 +1,32 @@ +{ + "Provider": "aws", + "CheckID": "eks_cluster_deletion_protection_enabled", + "CheckTitle": "Ensure EKS clusters have deletion protection enabled", + "CheckType": [ + "Software and Configuration Checks/AWS Security Best Practices/Resource Management" + ], + "ServiceName": "eks", + "SubServiceName": "", + "ResourceIdTemplate": "arn:partition:service:region:account-id:resource-id", + "Severity": "high", + "ResourceType": "AwsEksCluster", + "Description": "Ensure that your Amazon EKS clusters have deletion protection enabled to prevent accidental deletion of critical Kubernetes clusters.", + "Risk": "Without deletion protection, EKS clusters can be accidentally deleted through Terraform automation, AWS CLI commands, or the AWS console, leading to data loss and service disruption.", + "RelatedUrl": "https://docs.aws.amazon.com/eks/latest/userguide/deletion-protection.html", + "Remediation": { + "Code": { + "CLI": "aws eks update-cluster-config --region --name --deletion-protection", + "NativeIaC": "", + "Other": "", + "Terraform": "resource \"aws_eks_cluster\" \"example\" {\n name = \"example-cluster\"\n role_arn = aws_iam_role.example.arn\n deletion_protection = true\n # ... other configuration\n}" + }, + "Recommendation": { + "Text": "Enable deletion protection on all EKS clusters to prevent accidental deletion. This is especially important for production clusters and those managed through Infrastructure as Code (IaC) tools.", + "Url": "https://docs.aws.amazon.com/eks/latest/userguide/deletion-protection.html" + } + }, + "Categories": [], + "DependsOn": [], + "RelatedTo": [], + "Notes": "" +} diff --git a/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.py b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.py new file mode 100644 index 0000000000..4f57c25524 --- /dev/null +++ b/prowler/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled.py @@ -0,0 +1,21 @@ +from prowler.lib.check.models import Check, Check_Report_AWS +from prowler.providers.aws.services.eks.eks_client import eks_client + + +class eks_cluster_deletion_protection_enabled(Check): + def execute(self): + findings = [] + for cluster in eks_client.clusters: + report = Check_Report_AWS(metadata=self.metadata(), resource=cluster) + report.status = "PASS" + report.status_extended = ( + f"EKS cluster {cluster.name} has deletion protection enabled." + ) + if cluster.deletion_protection is False: + report.status = "FAIL" + report.status_extended = ( + f"EKS cluster {cluster.name} has deletion protection disabled." + ) + findings.append(report) + + return findings diff --git a/prowler/providers/aws/services/eks/eks_service.py b/prowler/providers/aws/services/eks/eks_service.py index e7b3ec389c..b0ccace49b 100644 --- a/prowler/providers/aws/services/eks/eks_service.py +++ b/prowler/providers/aws/services/eks/eks_service.py @@ -83,6 +83,10 @@ class EKS(AWSService): ]["publicAccessCidrs"] if "encryptionConfig" in describe_cluster["cluster"]: cluster.encryptionConfig = True + if "deletionProtection" in describe_cluster["cluster"]: + cluster.deletion_protection = describe_cluster["cluster"][ + "deletionProtection" + ] cluster.tags = [describe_cluster["cluster"].get("tags")] cluster.version = describe_cluster["cluster"].get("version", "") @@ -108,4 +112,5 @@ class EKSCluster(BaseModel): endpoint_private_access: bool = None public_access_cidrs: list[str] = [] encryptionConfig: bool = None + deletion_protection: bool = None tags: Optional[list] = [] diff --git a/tests/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled_test.py b/tests/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled_test.py new file mode 100644 index 0000000000..2317317e20 --- /dev/null +++ b/tests/providers/aws/services/eks/eks_cluster_deletion_protection_enabled/eks_cluster_deletion_protection_enabled_test.py @@ -0,0 +1,122 @@ +from unittest import mock + +from prowler.providers.aws.services.eks.eks_service import EKSCluster +from tests.providers.aws.utils import AWS_ACCOUNT_NUMBER, AWS_REGION_EU_WEST_1 + +cluster_name = "cluster_test" +cluster_arn = ( + f"arn:aws:eks:{AWS_REGION_EU_WEST_1}:{AWS_ACCOUNT_NUMBER}:cluster/{cluster_name}" +) + + +class Test_eks_cluster_deletion_protection_enabled: + def test_no_clusters(self): + eks_client = mock.MagicMock + eks_client.clusters = [] + with mock.patch( + "prowler.providers.aws.services.eks.eks_service.EKS", + eks_client, + ): + from prowler.providers.aws.services.eks.eks_cluster_deletion_protection_enabled.eks_cluster_deletion_protection_enabled import ( + eks_cluster_deletion_protection_enabled, + ) + + check = eks_cluster_deletion_protection_enabled() + result = check.execute() + assert len(result) == 0 + + def test_cluster_deletion_protection_disabled(self): + eks_client = mock.MagicMock + eks_client.clusters = [] + eks_client.clusters.append( + EKSCluster( + name=cluster_name, + arn=cluster_arn, + region=AWS_REGION_EU_WEST_1, + deletion_protection=False, + ) + ) + + with mock.patch( + "prowler.providers.aws.services.eks.eks_service.EKS", + eks_client, + ): + from prowler.providers.aws.services.eks.eks_cluster_deletion_protection_enabled.eks_cluster_deletion_protection_enabled import ( + eks_cluster_deletion_protection_enabled, + ) + + check = eks_cluster_deletion_protection_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "FAIL" + assert result[0].status_extended == ( + f"EKS cluster {cluster_name} has deletion protection disabled." + ) + assert result[0].resource_id == cluster_name + assert result[0].resource_arn == cluster_arn + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_cluster_deletion_protection_enabled(self): + eks_client = mock.MagicMock + eks_client.clusters = [] + eks_client.clusters.append( + EKSCluster( + name=cluster_name, + arn=cluster_arn, + region=AWS_REGION_EU_WEST_1, + deletion_protection=True, + ) + ) + + with mock.patch( + "prowler.providers.aws.services.eks.eks_service.EKS", + eks_client, + ): + from prowler.providers.aws.services.eks.eks_cluster_deletion_protection_enabled.eks_cluster_deletion_protection_enabled import ( + eks_cluster_deletion_protection_enabled, + ) + + check = eks_cluster_deletion_protection_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].status_extended == ( + f"EKS cluster {cluster_name} has deletion protection enabled." + ) + assert result[0].resource_id == cluster_name + assert result[0].resource_arn == cluster_arn + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION_EU_WEST_1 + + def test_cluster_deletion_protection_none(self): + eks_client = mock.MagicMock + eks_client.clusters = [] + eks_client.clusters.append( + EKSCluster( + name=cluster_name, + arn=cluster_arn, + region=AWS_REGION_EU_WEST_1, + deletion_protection=None, + ) + ) + + with mock.patch( + "prowler.providers.aws.services.eks.eks_service.EKS", + eks_client, + ): + from prowler.providers.aws.services.eks.eks_cluster_deletion_protection_enabled.eks_cluster_deletion_protection_enabled import ( + eks_cluster_deletion_protection_enabled, + ) + + check = eks_cluster_deletion_protection_enabled() + result = check.execute() + assert len(result) == 1 + assert result[0].status == "PASS" + assert result[0].status_extended == ( + f"EKS cluster {cluster_name} has deletion protection enabled." + ) + assert result[0].resource_id == cluster_name + assert result[0].resource_arn == cluster_arn + assert result[0].resource_tags == [] + assert result[0].region == AWS_REGION_EU_WEST_1 From f77897f81317a33f68fd68a58fec034f49823276 Mon Sep 17 00:00:00 2001 From: Chandrapal Badshah Date: Tue, 19 Aug 2025 20:19:21 +0530 Subject: [PATCH 30/30] feat: gpt-5 and gpt-5-mini integration with lighthouse (#8527) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Chandrapal Badshah <12944530+Chan9390@users.noreply.github.com> Co-authored-by: Adrián Jesús Peña Rodríguez --- api/CHANGELOG.md | 5 +++++ api/src/backend/api/models.py | 4 ++++ ui/CHANGELOG.md | 1 + ui/components/lighthouse/chatbot-config.tsx | 9 +++++++++ 4 files changed, 19 insertions(+) diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 61b9ed4773..14cb1d027c 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to the **Prowler API** are documented in this file. +## [1.12.0] (Prowler 5.11.0 - UNRELEASED) + +### Added +- Lighthouse support for OpenAI GPT-5 [(#8527)](https://github.com/prowler-cloud/prowler/pull/8527) + ## [1.11.0] (Prowler 5.10.0) ### Added diff --git a/api/src/backend/api/models.py b/api/src/backend/api/models.py index 97d10efc57..e08f9919a8 100644 --- a/api/src/backend/api/models.py +++ b/api/src/backend/api/models.py @@ -1752,6 +1752,10 @@ class LighthouseConfiguration(RowLevelSecurityProtectedModel): GPT_4O = "gpt-4o", _("GPT-4o Default") GPT_4O_MINI_2024_07_18 = "gpt-4o-mini-2024-07-18", _("GPT-4o Mini v2024-07-18") GPT_4O_MINI = "gpt-4o-mini", _("GPT-4o Mini Default") + GPT_5_2025_08_07 = "gpt-5-2025-08-07", _("GPT-5 v2025-08-07") + GPT_5 = "gpt-5", _("GPT-5 Default") + GPT_5_MINI_2025_08_07 = "gpt-5-mini-2025-08-07", _("GPT-5 Mini v2025-08-07") + GPT_5_MINI = "gpt-5-mini", _("GPT-5 Mini Default") id = models.UUIDField(primary_key=True, default=uuid4, editable=False) inserted_at = models.DateTimeField(auto_now_add=True, editable=False) diff --git a/ui/CHANGELOG.md b/ui/CHANGELOG.md index 6e5521eb28..ee939ada4e 100644 --- a/ui/CHANGELOG.md +++ b/ui/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to the **Prowler UI** are documented in this file. - `Cloud Provider` type filter to providers page [(#8473)](https://github.com/prowler-cloud/prowler/pull/8473) - New menu item under Configuration section for quick access to the Mutelist [(#8444)](https://github.com/prowler-cloud/prowler/pull/8444) - Resource agent to Lighthouse for querying resource information [(#8509)](https://github.com/prowler-cloud/prowler/pull/8509) +- Lighthouse support for OpenAI GPT-5 [(#8527)](https://github.com/prowler-cloud/prowler/pull/8527) ### 🔄 Changed diff --git a/ui/components/lighthouse/chatbot-config.tsx b/ui/components/lighthouse/chatbot-config.tsx index 4ad5d46d4e..159722a501 100644 --- a/ui/components/lighthouse/chatbot-config.tsx +++ b/ui/components/lighthouse/chatbot-config.tsx @@ -124,6 +124,15 @@ export const ChatbotConfig = ({ > GPT-4o Mini + + GPT-5 + + + GPT-5 Mini + )} />

V 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 z z=k~Lu8oBZVn+TscdqK({){yhRk%vA&wKUe=++J8s7QkcOu%3mR%IGie`zQv$tXJuJ zGfz)VQR*rfuQSEizCX`!P28yj!~d@MfRP^4CPs;B$s!mKJ*y$`L69 zIc&En9WCQ0Zh&?bEz|XAxmbt60OA>p+#@a#c9F6jn1SBY+Y1H0U1PQ~-Lo*!KR$k^ z3et#*fk7=Pa#l8)do)*iDm{qKRe2tIG@TT>DKBWTVNRPuNSQq2L~il6tr9lJVpT{^ z@~@Q4y#-OlCN(jV8y4WAd2l3gnDMh^eKO_#L>sb$k`3P9f2E^_SIJ1oD&q)I$^b`< zpbQ$R!eogPoX>-l7bAaC$^GT-n9a~aV?M{lZ!3Q^r_;5znBG(xX6+F%2!r~G=b6Do z9(%1YD#h`0h>CJzuuBL>W1Wxn#d7oB{eWFv9pkuZ{;0a|PrpI`{e{}Qpp3Utqp@_o zo$h*~$BvzbS-ZX3BOeDd1xgb$Ke_C^eFc90n%rC$ZSDQwDGYqSC_gKM4{S>#OSfqp zUb(UYN*G@Phm^`XT5ScGu3eVO{H$uU58KO|G`j73f8E=b84%c@Q)oizOjq#0iMOGI zNEjdl1o2xSa<56;8}1yAxWVJp*H@P+l4cEMK(Xy@=V;GO+CyH*hNWH+FW?JI{06^-|q*vwrUC*P*Mzch$;!q*Ba%(c=~(`yC3znJr-d0n9=E6GK3 zU!b52;C#mmUa%Y;Fw2WIreW?s*_@13vYjVh0wpzXTfdVbntJQ4f3^tSVC2g=sNEh6 z5PNSD5&XmSR5|m!%?8^knsgG-=`xC$xIdmR)mqxJF~ipHZ+#i-W(dIl#F3qmZHr7gc&ohNRfYt{9A%wF(v7 ztx$UJ1N~PQ8a>`xo+be9LM7LTDr}pc{fpH7%Rd=^oWkc=Fk|DZFEzhJhAN|#^_64) zA{^Vf!TYhP^3bhA1@bpzNv^=zoUR$e9Wa8042v#zJYqM~K$9cY#UZ`eN8(kt-L zT?t=9+HAUSEIQ0}nO=(+exRAjs zHPw5KreG||^ajYjqU{CQPgVj>7-C|f0&Q=0MC*(}rRpv3JVhzwk#B;Wj9VGfm!wh~ zy~QGZ09_5i+*;H_rKVPQhQwI(?Z_vwSbB8@Q^0ZsKJI-GEpK2j3G{Zoe^5r-K6QZw ztkKZz%O3SZ-q%5=78+|(^IxfSjh}x)kES-M=a{~$EW#zYH&qzS;BzQKeUoe-c0=5v&$v3OLlAFv)5F5r_qz{6DilcE3 z!|P0d0?&Sc`W%6P$AuIqjfRN#aGAtsPVhmqtNZ6QDUIem$@g2{+Q5i(Bo^mD6nHwA zrI)W^QGVKlV6)bjB8-F^@_DgxDuJhIYGM!PFZii<6uYH4!h;E4etHu@fL=;el8LC6 zfxWxrdFDZc6vNn?gn~L4YME#;3_ohOb2%8S1*B)_@>MpskC-nBpg@1Ih02U94E{P^nz2`3=nJOr4=)ThWZfrnq%z_T8yrkq-xPt;rTUnvsTv zJ4(h9%1hzeuRdlb_Cx^Ql_X8nZAxV0-lrKcklC&GXfiaRJj$Cs^_vH$JQhwyX)@Ej z$3r8V6VbP+t^nXm{@j*4^OfFA7DJMVIq9dM0Ix(2jkGcwV|Wv)X*|45%X()ld^GnmW;H@C&M=vOBs!HEnUH7!^;e_Bfk9dDlZLoRnx2G!) zgUZ;lkuEosfY&LZ8fB5umO@uo5pN9>rw-2RT_)+P)YY_Xvmz&TWNjdNoqrRxg$RXO zZ$mXAVEcK}z5ya8A;xBXA1j}-EUTYa3|Hu_fA3?2G~4@&gy{gt15~`+i6hCj9Pc6@<7e%a%6I+rwrm2_U81y(KVSDt2Sj4;imc zHbs-nVsxe==&9h$l<`Xr`p7FVU{S$?usfWkvElI5z=+MQ*SR}30B$o8Krf;6d5%0g z)1?aU)~=m(cD^aD5Q0#a!-+vxC<>@mpP9jVBJP2p<2}Q^C5V7n+fiz8epbi15Br|**0bkKSLry9z;E zfuGa2M;R4Xz?WXJCR5L}_h`!roWb654a{s(=e@K-@vn@F#;~eMn5&cb*C(>UiZuoO4`9PuZ1JZXiv0pjevSu7B*Csj8 z4_GdNM?VKZ9DV{=hj@70)2aD(RXexQNs7%bApj_lnh zeyuRsnU{Hyk+yU^?>C9+euh*3MxoH*ieC<+#2?0)Q&%w#J*AVyBZIa%r>yG#+2E4( zuXYKCe9sjSTkCpJ%VDuwJ`bMj664zG_l|(sqPP5 zPL#qal8Zm+e8TbB=WZ)!t+$$jl?C@q`|MRF6O^lY+pv48=y>6a=lN(5JWniZz_qbE zJvH~_Icd%Odd^>))7R3iYvEu0bbCl|wA;NMyWQQrojWv_{p;~lCkQh7Q;&GsJzOl} zuDUL^X*)k>s+aXQ%0v#Ask)bWb&?!Go#22CNcXWsRxD4F?v6@mA@Q&-)8)1~^9~gI z3R7mQRrV;XpzmFpu4G|Or=2?yP%5=zu?JIE^m-Tx&|l2-jXG@sTJ5hb{Wm&71mPA?6+t!XB`tm=zQ^2w#h$)8tW`r4IcTNf12<9d7j?S^9pc=cLi|kU zqK}?*zI1SO&{0f`NlJ`*j5a!mkb7Rtj$#YP_gy{8h_Ey-uoL-IgyL0N8}befwL;y9 zlpflNL|tzF!v}KAGLjuf85Z9Z8=G>vMhNIFiF}JpYJqb!!Hc@$x85|gQNz3vUZfp9 zb^J7S*2(Q5Q8e|VnKJUV29&PuoftZqG6Qm^;vD$8m5!aZLO;$UX$e#-hgAN=P6G*u=dkoxA?SWdj$b z7pNq8LW4-;Tfc@e(bdo$@)-^m9s99Yn+Zko20)uHHezV%i+6O-vdR;^srFr;Q5cGwp zbZduhDxB`u^o)!iCtzBpklal8gC)J|F>JLuL!Y{p`y#NkQL9Aw9QCbrJk&wsrEuJF{Flf&_E;5Mf7d0PUM2DZW0=s(sZAg#LVgUN^BVKS!> z{Sg82eWbpF#BF}DE1Z}4_v8a!yeE5B(auO>*tnhV!)+(u!#CC^o~sn5vZY@YL zZ6SRqMtLREQSrp*>hYCCPjBpc?ztgls*|4`|JtqA!I8!_bMMI+Z;x5d5a`X}6jPEs z(^>6kUmbjnQNO{!%S4ZgFNEx9RF-DGXGoO*OPfmSuVNchG=hr6UfY#+)Wep(pCMV08Y!ePZg+5&k z4T<#9=q_3>(D7)Yx)(-hd1-X|0?39WS@#d2t=V+v0$JL3R2Hd2tlizs*5q4=)?bC$ zAWO6f3(z=PAo9pobQnS!qHSmre46^UaBn<2~gjo`0&S@gXJod z7eWE(cMuR8HiOLX^w>uw!?F{@ZvYv~87G5Ob~sPCezerh$xJENmW7=h3*|a92B0!X zMm;nFTy#Yc4|7(_REj12u@_zVC>p7vZ1V}{w-*Ts3JaA;d~INw`$GVI5fbEbzuYCG z&|b|EOR-E-YhX@jb>cc~IG&j7ryq*h)8voc$NtXcvK*DUZq1%JT4dc(md5VtV5U^< z+VlKCY4srxrgpAM#Ur)RjanAfWNU)7E%%)%_t#oe`ChifjHdON*w|REjGdpAe8-~b z)GD3t(|aBriti3r%ff~9AYB8@Ue-5Irs*oI=3E_$S{ewm=679J$6}Ct>nSx+4O*zw zJM>BfLY<4!eJlI>#QUjm*&Cfq!at!?spFFps~>v@ABLB zv$xBkOfylyGeXoiN;tJLV#2*f)hCs<)^bPM{W-ZmVQh0Vw^%wvdG7Kg$a73rv*c#k z<-}EcMO8s;aq<3PjkjK0eV@2I-}j`(f5iylZXwWU$i`M( zs5@F8Z4sKBlqCqGa((LQ>B%W}233vuUMrc=LJYsMGT7J{yHNf1v1Yg1>VptJ=X})` zxA1%#)(m+gE1T<+df?A8*+QJvEE0j}Lxn*=>J0E->4~$LYaBRPufT0W@S`)wPs3w( zSFg~1ZEqh($)|=`hV3MR2t}jx6)U$c&DtV3`>jtgELZS^H@k>ieFzZX=T}or4y`H> zDsZ7!9jz_#rR67x-PuQa$$UO9+56i1y0bhuTcS8|^o%wiiN`@h#pyY-Sh{bwq$n{S z7}Re(0jhzkF*edB=2O%&Cd@# zJ6nq{>m-$s}Zvfmr?9LdRblvpP2yGheBijB3 zSBc4+(#`9zYE3$U=Sv%auAkl;hB+aXS|s0b0+a$AupL9Xdb~=~x!eZRU-~k7*oELB z;yb&1r_fF&=sFSVJ?1(Hz+FRp_Yd<*pE5nI@9&Z+>GHyTVyIbIdU9OAg$KgbZV9=b zEg|%0hfUT(2nWwF6$mM`T0(Bxkb+nVQt;zYLyC_-qNapPATdkGNY6W&&bcp$N)a4K zWUy;haC?&807`jiHNd#fuT(I|Z~!9D!ceS)Tn(l6kKzRR5xP1mij7MWSEJ6p5ZkKv z>$kWy8wn1kllV)Ujqz~cU~?x0zqWrh(Hd0z*k8`zfAG@3U$8I4Tzfs{0FdU55?+-; zRRg`$BJ~cqA^_r{A-Xfe!nJ+ypbmL%um!gS=~rBay1!W8+{UM(O;)Znl`}WT8Mc;F zDBbit-e!^UKl@wOQX$F&&Hd=P*BTX^{lS`uV3%|<%8Zv}bG#$#XZac&0g6q~*$v>g zvj!y$SKcnc>*bZ=zEUVx)p_ec$^PXmbdM|}21t27#rLrZAfvYaQ$LJ0B6ypXNd=IS zV4#-`|?O*87X|^DHy| zD(8ob3O*l-r?jw=n}&YX$S9r@@EpFvnAAW*y1~!bSu)_mtQ~UydonvAkGC)G-OrWp zjBuY25SA3DXwq$G+KWQ+93Vms!*sjz6C(x&kamdk53Bf-HoH=CTYmRF?;6OM3^mpI zLJW;va@$VK-j8}<1qfji2$L-;&I4@twvV@m%;wV6;y>6tZa1F=ym;t>-J6G$On&CJ zp14>N5s}$aQfR%sIp=N?W>q1-!;T9yWhGe%r6eY3&Fx6PXtclfPtf=7PO?h?{B9tx z)>EC>(9Heffz&9m{T*4+(b3JBwyM6F?xHM05m=MfgVzspmJqW*X==BIHZi5ZoO-8# zUT_VSmExE-st~2ELwrg|DxI(>V!lQ`GS&UC%}zYG`ahSHzK{2N_mEr1Iz;yVPwa$4BJW+A(|Yw{$@khFI#G-HC;1=Ph+i(A-!F4{s zBqfD3v6=<$#(Tu=#ZBU9y2iWnOoP{kUD5GqY`zjk2oxGR#J`zHaTa7C*D*q>gebs3 z^KsZdQz+JGUqD=LIJs}3x)+lmx%>Yv8X!8)lxm>SolCdz!fn#rjJT=^i{S9O*q=Nb z2olb)vBU#+G$UOACyx~IVK3#a?4Hx+(0%KBEn;2owiy2mZ32=2|32msSB2>NX!Y%1 zjj@j8dgan;=mMLqH5w4cqmGGBN3lNK{XiIuw{QWdP7+!&s7;XSsng}~s03t_`*`Vx z#ON1(ijSiefO{lJ?!0p3$wA;>O8yN}vmT)2(Sb!fwOJYSlLm|1(TP)rfY0M>JlL@` zWe_fQsveB*Rkaq=O$%Xv35}`}CZYTjTXd-dvQUJ}&Hn6rG4Z@-8YxpriM|SVV$$tV z--Q?^izS4yukp4=2S*-UCeEg&ScZh3I8Fl;aAi3NeI##>XVJ~#bAxD>E0tAzKhJx( zI(kcJOOs|oG10`&;jp@5E#0-lh4oC3m#6W*oUwO9c(=B&jwG?rvV3NtrFA*Dtj+E> z$S_lmXmRd9;CiXzr*IHz71aajSoY@RU}FSGHQ2>zOVH<`*~~zt7qB9E+b4%nd1qO` zZ{3+-uJJSK@l_iNp3$azd^+WV;*W#R`x_`O$JUR*hNLkcKA6__xMHTREXV}x*7Y?N z#+A>2d?e$o>|q0AM;F8%$C%jheFVOzhCS}REXlLoJ~?mAkEkD#g(8`d;~(z@z?;*hT&hFJRE}2~{N012Ct2&xPza zqr+kPgwVR5N7zDP!1sww1RP01+hI>9hq2qHWRqvf>gA_s4XDZDK?jCH=&xCQhvpNp z5P0R|gDVDvMf9dH!(phW3oqlPS#HC^6f_l0-h>Un{%~$kYo`0beL=Gy^k=M)PW*@3?t_}P{!H`sR)Z)ijsfE0MAI297F-CT?qTq-_{6x zP>V0zxdkUmK`;LYPfaD{&P|ltUZDE#{TQ=>k_%Y0@gC#-H@1xmO5T%7IOg~lpbK*^ z0j)cxPiVSt|MmFb=R-=9?V`HWiT(Fh79|0X%ThVwlhA)-ECPVXCBMH~<4+m{7R(VK z(Tkn|^IZRp^^*Z(ECT5#e=U?z-gPLMveUO;yI=of;M|f(nXA}KZm5mdR_C$wrtumeHXpU!ZdW-o-m1+EmedivUCXJ&9YsxpK^zX!me{qASkKHKB;!1Ci1 zfAhS~9r6s)tv6O&qmLXIh}rW>s;7ADAev~|9XXWv#5FuQxj7G2j%P?AZ%q2crwvDZ zet_K0&qubbKH4);ryRZVL2@8a&qPPD&{xg|yLhe~rSptm^ZZsyM5I)u7Dt|>d$T%m zPX-|!hs!}k6T-y9qs0<8#pUTees-yK$iGH7ElALjd(^DG(e$g;UzU|kDKR+eva*-w zGE<{zZB4J`9(evd};W&bF=pw-19Xo{(W>><2dXL>; zaT#!FCM74EtG7XD=`kBv#yj=kRkvldW{QNSLqS2cy)hD*(cSHM=p{pNVuSq<@AmJk zGC20-JsS-CK0|(@IwK`1y6ScwHYd=QJsXhBP!udBt$m*MwUr4a=ErDyn=1#tvL^pe zpseNn&h%U^TXm=U-xzw247q=RrEIF7+T@5=S4B?mHR`0nTJJk|p8Pg4E${A?8xXKo ztW}>JdFIfaXQNzGFms%QqFQ%~;WOxs1_8i}Z(~V-(thcqfBfyV^w3k1Y z-qgg3UR?fAWrrrr+dY1!t=Gh z{)97qY;t+EOj*!y_KjdH45}l0=3?bfM!px&J=F+RO#M1%hjvDHM@(w++M^dTe>_TPpsb-tBiPz`N&yAvrcp${Lp-|(qh)Q=ywcb@V{#bB3MiU0G7-}6H1-!AcTM92_5HZ;bb zGFdn4?{3+(n5#UgvrW<=2E^x~b>ariPM| zfnF!6bQ%gPO}XJ5ymN;+Kx4C7vH^JzHV3TGX1URV(%4g&Q>71tpvb~+{2%KrWiX0m zPX*Ye2f*F-e>KHB*3{2T&5T&+E4Mj*PF!ih1IR?uJ)B~LuU&wxLAPwRt^kbQguSve zzu@ivaZn8ta6qcQs<^){pOMEq1^7uT2|3NCu5mCOqpm}v57%$cVV<5!QmWoSLA8LR z-5)id9nBVgFAT5fj%QM<&*#F?-MM5@{;W|h$xsp|sg;O{%4&0IzE;e{|2Z*hzFunY z=TG9G2^$noWH+V|IrlF<)JY)C!O}j^Pq=03O)zpi#1v7k&OxDosa-uHs6S9hQavbA zDg!Yrklev|#d>G49#3K56AB9UY_abMDhkREWMq`cj8@pbpZ4+p>o)bF4)pGg&E|e@ zm603JPy>~nniCvslWOkqc^OSP#aFmSA3WE2dp{{W<&Il)6XA(kH2)_*QZX;!ms7l# zjUD|4`13Qrg8;vjewKKa)+3X|#KO|X12>6YU^_ASpVjvK0cm`gT_6}HUZE&9m?mn7 zABV8>b3(8zobY-ISq^o6SV(^;9nc7s`GZ>!?`vFdf45)4H`bp2k$E3#e{aKGGE)de z=X($H)x78;WvKrER226ulri&T>I;13`~LtAJ}4zYrU0h^B|)dA-=w(pL?;^k57xCrRhF;~TP;*QLm)bzkt568k*@G}7_Wo!)%DxHaOh6mK50lh*u%VNb6+j~@F4-${*xjDDX>z+QGFy3*@ zjV-`@8G=?l>W(L^KNa6HN%#>iq=)z2)m)iItwu^7U|b_p#`k)h%rF|;!7WxVR0sGu zV3qyE=}I`3kPm@OHTdUR088~2in&!!ejg$=dtSBl+jQT}k%S*^k6L_0LZYl!N^*1{ zds+F31h^nqmC6d~|L1AY4+OcB8;0kI2gt^~Gz6+XVY12G!AS`Ej@)2clwu_}Zp6sV zn(Rl4(1G3bP@p3l{L$gba?+Y8=MDWlH#fIbwc4S#WKH*N#vSNTggaitWtp>rAa|15 z7RTY52JFb0>lOPSBDWa7z7o(gXn!%O;L#J<&vN&9Uq#API91~|c30hp&!K18k6Gh43KqBt@Lv>VB{Hrox& zdeCH{7)FHw6^8Igucq5#gRA#Lo^J>HHs!4^eTG>w=)a4wzpGl9xz0PrVM2wxEDZ1K zo-UxY^?D-LNY#c_z~+@NavbpKH2Dmmf=&tK3|gD_q+{;g@{^i_Vozst8T565+ubVB zSZWLL<(p>h!oq;f+o{5-rR482{KcK%_E`GUhgW~l<*0D1S)lWqetd42t3lT5ADfg9 zf&@3+n8#|vv!%YZ*t8D!1tx&?hR_z#m9xUgq3@Pb`f#wvW2LE%$1{%n zw12t6va(`exT&m+Dr6l2YQXc-U#H(hy8L^rAOB4e+N&n*UE^6aU0?lhDku6C#*WcH z77HIh&7VhDHbCM1b>%o)){(CudffbCa+B0DLIPTO<;eKerF;`>I)J=bHtAvX6OaL` zX_)v>J;zpa277@tA7g}GO(vVwJk$!_mvtVZih-UF6nY4+24akChn(_cAQ)Mz1pGdW zp$i$dx}(dg6!b1KeC@J$cy!?H@O{9+J;{_{bHv@;a?_~#U*}R4HxPYjzp>vwQO(`c zw^6A3N##Oj?A{fslfm8638nAmPi_RFk*i>1WDk=TKf7ZD_1wX6Cs67|a;jgoCB;6k zv1^FS($mt$-;KE+K{UNYZQ*|MCpS&n9kbiy%95=JGx)r&~vd9|4ql*-H^r;Wl>8BVZ+<* z4nf0z^KottP+`^wLbRLSL8G2ajCT(K0n}&3s8@SZUfFTJ=gC)BKR0_q2eAb{x*pxW zT&8|B=YKGipr7r)r{oHtza5n6A6V3x)9kWZgBMr;EMXXdf*r5#k9yYZ4h55>k#=k$&7k|~xe`iNen zT^j?r7)aD{*;vf%K=J-O3DJ9Y*q2`ZBYS))e!j6xF>oygVwNBcgn*>N!T~_4gM)>& zToz^;dOqqNu!EMJ2kcfJaht_TAxlU>sm(4DbZaQ8zx4y}Z$5A6Q)C%>@V~P%&|yFL z1K!QR>)DdDKIo+~GJ`$vS!++qk5Hbb{hN{g`*#67>`GzOUC3&7TN*-jo+??+f`NsF zg}hg2RPxeQ(eeGlERqJe6coch`G|owk)S&m4ELR+{~e?!}&yOl!8Jk-vtDo9*WuCpimSWGV+<1%yh ze)RUOvACj8wP$6dw8Xb1J)No!B4Kt`8{7K$Dd;to)lH`3$3LX+TodA>hbOf8(cE0y)z*P+@dQ%@(d30~I?-0#n!o?VP-(Dt_0jJBL}2N`EbPRC@q>Sxpri#^#Svc(ECZUFrQCCz?J`~;*c&5px+ zhc`byhY)bWQ}5Pq8Fls*R!RQT>dH+5HJ+a+B25pdO!xj!K+i$UPRDw%do8y8VvPYc zpuTVTT9z3A*P+N{OL4jGT#OAX>R}AjLimVbO$X_-_5P;FNI&nJ*HE3unv|Be5jg97 zf;IJCjYVIFmtxz>np)Lbv%^|!p zyof<5lL?Io8*~;uuD0LN_5*^gXED64{w1E|<$NlfI(fPRP*XouL_aU(r?V7S7ugk_ zr%6KQe|aZy0Awaf{`az;h6c668~r??i0KGN@WNP)5p0WmIa)Y+QxB3{Ves#<-2`^} zy`!2=Obj%a7=+>z&6n(ar2Pyzah~MZ$H1hZAM5JhK!m17rPGA|#x9h=UX&uk{Iv{m zNcaR+FdcyCm1Z2~8vKRaVv(^+iF7tUEipC48n{}#EC48suaRo-J)t{Qfd7IH70J{+ z1`}Mdfs-gxdNEPK{@|Yr2t(u_{Zu3-Jp_RAU6mnDkNhAC7+!w*@+`-W86OTdzgbM< z$%rYwG+D*S`6YCR>xYr3ak|{!Uq=rgfD!4g3LJ-tugnqsiW2(`t_>CiF$qz8|6GU} zGlLJ0MkN7@i4*b7-jMh2|7j^PfLZ?g2Q&ou5u@jSAO?omp-%Y?>WdmM5d9EOFGW*J z%Kpo)nTNDHzb$bYSk^;+yn*B=qNLLwF?(YKT^#i!S0wducZCxJ;<>zUpwAg)A&q~- z?QRGne8Is{0|q9zUaIgNx2Y%w>wg1kRA8=pP()nd;xHouDdk~D`i(j6b(jZV+Z@yT zz?n`bEA?*_kND^}V=DBfEcC|g{ie*b!K{Nb3;Y)XXl9vttD>TFLZUNDqBC-0;~!Jv zfEggbUTA^ZGS53#3-}j>ts=M*NGhn+FRxXA?gYj;B`P{8DLTa+0M<$TV^G@|**Ury z{<`J)0+h4YP#)Les}&fH*re_MfT_6J#I8w@ z>8ItG7$j$ABs|fobF+GkopB)v5`Cy^8 z`(k3fLQ35K)kAOB6UFJohnjNk>U-znpu>j&`}+mNYxz1}%|1Zm?{e{j=2HAE8gOH$ zOgX(vU&6shf}#F1%j@CwXzo<+^fW(aBtSd@g#Sf-iSfbsTRh>J$Kg8{NQI^VY>nqF$Rvll^sihF{7!d$ zfNCV%BSIbR-NmR2V9}U#uKIX$9v_`-w&SHg5w6;DSjo!?2??F!CB?+Z0+l+5`_siH zmE8lGlf`lcj^EBZ8=kh+B7Gh#nDbQ^r>;WZ9*gXS5)uN;JW!}1*n5=@(*sV6FqdGh>sm>wc zYkAo!QDmtc-$$pje(obZoLj@|ikYwz3)YKm58VojhWE{GrCiW}%Q9A*9hkp#isB^7 z8T0cqnfCxsX3G3~cIpH_#T0DvtQ!9y9_t|U2VA1Ma8~pv_YQrj7*G72N*lv_-rAQc zl$_58v$vw2^dFn&*lbqjYISZ|aifJpFE?V_?3u)ixc<>_MlQnd3AsxDes($EL;85W zKZ0Tsi_X2iJFW**PaXB2BSpa`u&`Tp+NTd=6FW7&Un(!0WsB5VO}lD_tA4Jm*UtLF zhX~x7AKg1+BS2K9qa#9UJhr@sPWPOPqvQr&)0qPZC|=Rk{1nEEA+ZIa(=j=O{mQa3 z6Vo+tqvwlPBpX_7GjNW@D$e)EmXQan%T--I%xHXS;W#*x$Tf>hVj&>znC6sgQ zVX>p+-us2Qxvkn4`mlU+y{^pkCkvQ6ANSLnv5FD{d~~9KT`HEkSN;uF`g!LHWBnAq zH|U!mDqwCBvvfn`NGb~%ogs&<=KN}ai`k4NVI`|Tq{87yU%mU=?FNuxYcZc6 zF8D}Qc)iSWgKs-ALe0(1fyzCt_FXz)BooagV)K+M?}$)(mN_p$TE~wMu#n~!y#aN= zS34@ma)o?wVO*_7Gxgel$l&yEu#2{NCB2yR`O;fM!jg(d|8x`mG7I9*jR8W}y0#<{k{#36pj>X5*!SH-;~&sJEf;MuSXx?B?Cl+d;R3oRy5j)- zjLk~t$4O&mZ=S|3Cq!&kOoR_H{6PEE0@l)J8=|@>A$yVO!`6Dz^!)XLITzgTs4WO+CNRkvPb&r9ev91?94ig_K-f8-ofcI5YI^1ZxMKYj@$4S23F{vagW>hsM?$)I{Q z(MIAjR1l(Q=9ck9bE!=GWA3z53y1LQfgAnl2^z}<(^#n~LgVaq4+bLV;*E;&e1ei4 zXG5E&i&n8S=Z6SE;2JL--I*`tJs6Y{)0;-S_LXj{1TVy&4oe?sgnPLUc?`-F&vC_} z9b@UDNa z6Xl6A5bQYfG}PmS|f1;Sj1F$x}l~Is7MiemXTy z{w~)W$}lAsNe`;M>8;V}di>}}Y|ck}dbc7TpjrjM-n6!KneVnaNEHiw2QvR51Z#Sx zvG%>#1szYH`tLJ(qN1WNuGJZw?!xdl={$d8ZHK0?*{(|r$vQOMnK>N|s5(hm)^bAu znOvm%&lOIMOb<}C>M!dpXzTTsTEpz zGTH5R1G!XeNiH>~D~-|Q7Z(Tfmlc!p;$7o;l9Xx0Ye~rpW5{z~BB;FGd3`(qr1QkHCIrD`u-v}lb@ zf;G-dorN%|uRv*U5#ZG*pegGd!qXt&^6)qh3fkscqIBVCZ%;7dyb7@ysON${(Wq5z zJReHR5sSi~fBtgjO7nf8%^EOi%xj6TowmSyvMy$jX6H9&W{IsBNKa=KL&KgUeY_ZLpRIbf+$_+=vqtm_PZDHzAmjp2JR+s+=Q6+`(0BbIL_q*0;Iuj0 z%gw=Iyk9;Mx1r|s)6kDSiJD0gl~(!F9P^KQRn;%{X#E7;&|f;v=;Zjj7nIc{J`=>O zSq<=IqSHQc<^B)>_|U>V&=-?$ohLyOiF{KpyJzl~e<@B7yUL;%UrN4zs@L)-a73r( zbDV6~sUU3;imR?D43wfPAK>CHUR<=bH3TH-H}}b-f-$?mwQ(AkbUPW8(;1UpL2-vd z9m$aqrMZLnhtYU{zNUiAu=9DdNwz&;c!)FEHkCtg(^}K+a($DG=2?^F<_Q4j;B^!Bqzd(LvV6JC z+*--7D3I-w%_xt!H_GulEY{(Zc|kv!I6Tp^MIRL`#HZx>-L98sYuB>qI5Z!=rTlZ- zV`i;d@k=vMr_Q?-MhTOh%;hnjdfx>YR5@R2zci!E_DJ0BnZtG-2dCe`FJUsTR4lXa zZDXNUVRO05$~YZEYx=q^Ys~Rz2Ia38nRNe{rtH8Yncxub!qntlI@1ibo-S?Cr?Eo z%D1QO;p_SxL}P}Z06#bH;|64hO=wH^!@IzFzN#}hW8zD4m)o($Z_*%H96pop*%`?Q zI6OpvSCre%)eO^B7a;^6cnItfg=~*Z`=H}Xu#}p8*eNdBz5F`aHyzZp-$PLS*8qJp zeo%!!&S>;8pG;N{5v|;7=zFqlc+^iiV%ra19Uq;W*sJ66O8L>srLyl1ikM(2o;Wa% zFmz{fT_bC-b)w=P3$ee&Up#r1n5NB{`k(JJr+PklN)`PeV^vC7nzS(`0sZi#Xb ztj?lOUC3L!9FBen9sd-jHuBdFR6{VomJE~IXl5*T8t6c{=oH=AI@5+w6}fyR0u7DN zzcx%w9<(?*;;Lq{(4ky#3A;}$?RO6ZMM0Srf_^v6l~Ygm>DyKLW$Xhv@r?&m9s&NB z3txI$r&ax?D%Qbfqdoo4xz6o6D1uF~Ih_sNcD!axv+Rrn@TW-sOHFhT2;z6pYQX68 zR&}^|>G4ZPr`eA%cBG^o&MBM(X;d}rj~F(q)${A!5{Gnl`}MdBowXgjKSE-%(b-oh zplrQgyG}w7-pT<1!TuQ6%cC}*+v7YS4JgV(wxVyhnfAK?=*PWePmdDS#$!u{t?5pd z(XR)mKHlxy7*8{XroJz4xm3LGJE%TYF&{4UgsmtUmm+d zx#&=z9|@lSoUfMZ|Ko8XauTBh@gt{HA`k0oRJlSEg!KyggWY;O$=op%{v_D<8^AF3 zACGFAul0_!Hw3@O!*rcvM{H2A1YYc?C%%E5BA-gq2}_QQ9}9-z4QR&qR_-$rA( z)sg*Ve|V4O3dn9)uUx{CY;8>=%}uZB#5q_+s^~YMC1=W{DYP5^ir`D~D7SrkO~H66 zg~@(+QM)4ENR0}BB8v?R7a=7FYC%G=OpJ`}{6x|FAVeWBbc5Rme{dmTeZ|TZ>6{K0 zXXi}n=VPBGaG;NSu+GRo6fcxg5>QwYJuEfPyW=sfsb%{WW;?*FZ%P!1=PXxVK zu1jHyt0X}|xkT!K?;HGC1$!q~7;KA)G392C>*JD9{}m>-roGS`s#UQ+6?A6|IDj=2 zn!rW%OgcNis*ilLU;g zHCnuHsMY&WAj}yk(Q(LlXcBl?X$*goZN&2g<8I5vEp@K2j)Ajzo}#8W8&hRvnzH?_ z+x@9RSMXIgxxx};0^+x^9<7`kKeg4_#w~IG4-Y&EweN1fDY~ci9e$ACByaWE7Gn&Z zPEOqA+C5dm=3mV>ybrQs>@0;Yiom3YW#v^=2hj>+;=rWf7|3^$8ICHCMkN(wg!-W69mU2AXO9hNxPSg#{^JLJ_3bAM|*OLgz^g0Qb~d4mt)KA3v4d753>*@FBE0ND<& zS0OIe8QJ%3P8S`nFHIA%I5)!WwvvY@8}*;hrgU0v#@6}hr5vVWxts{&lQRYDM)tcwVf^H`9zDtSxBVwv^N7Tx%czwcU#%h>WFM+W&ntt z_KnHnaVhknst3V7OE6a-JeeA;zZu5iYKp|c%Gw$*Jn1;8ep=2G{wc%22kuWV{WGCh zNMfLNDoipxjBd5>WhwdZ#FjzLz>lcPX`;b+!#7g(04Dt1D`3-XKmrZJFmi$bCb z3W-07;~zjGg>W(TdUZu z5%~29?n8D`?+(MHumD+GFW6JAoTD%jlyroGA^{!a;d`)_IAsN6KEN?%4s;t(TNoJo zpioFQQ9RgVec#P^>6r_OW7xyLVMs?{MDl4gMM&t!1D&vYCm|_1m?+`1E>vo^A5ct~ zo4oLda;7i9-R1W9FubJhE;n1Hw{rda(VV-nVSo{_@%?*2SaxZe`tn9_G>yxvi|fZ9 zeY?)LhphUbh*C$|pM7WjTuf7EE8Y*$D+rfgx4SCLYdB)gGWt{HI%THM!@UAGMZQc< z*&zuX?~V0A#tV%#lp=5uCo+4ooq$tNUh()YN2kA4i$tR}?Y1yC(H=YTfoPn|$-FLb zie$BGs1c&QYHwiB>7mhRV4;Askjd28ZWS{?b3?|-jDgEwE@0EU!Txj*9L{^!c_Jb; z`FZN_STHoYQraJpTrOlxnYX#z?)YW2UinxCwpuw{aIg7vIri?%U8;l~K`M$UMJZaNGvp^z&KzEFRO?QGRpSEhwuUlF72Dde zA;ftIluE8zOHv+$=z5k z*(N6IV6?fOG0J0OBAD+UWSi-~+_{1o4f;W+n|?lCqa}XiVC7qyByvR`cUKVJUTF%S^##yaH)UVg510x6!8ilqr%tq>nElf5oy(QL}!b00^$!JY!M9=rn*b#IZj5mw?R$cg9bXNRBRLsf}S3K!z5K$^*u7| z1l3pAom5THhPO(+#2~WhR!!O~4@uCPVlmDK_i1u8Q_w4iTEGJX=NG)iDyC=w_m zJ#M3y*jh~H(tM>CqEQY=%<`t8iT zVwdnW=rZ%+xEAStSWvFvt>Za$Z^fwyjs=n*(az=&oruwn$3W~)jlvAU;1o_32eD9H z?m&eIE+VJ6M`Kwg-k?v0DtjfuNMOCiBEO2lWfsCP9%kOW&_ScS;M(R`i!cNc@j;AKr(U5MIr4o^=+iBK5?tK!G zUla2Pu;2)DM{BYGj6R|TTlxo>DWYSaTpC}~*M`%@jClFzQ?xxH;kd^Vn8%gdL%JHY zz408VDG@@$-k_#D`(@W{Nau<)(L<~jqU~67(((HV=ReJ4_?9J?b#aKZvz`F zFPxnYGdAcLXk{?gq$CB4lLapR`4;$*Nar@40|;seRiLx#jKAsnW3K!_*j3&sNMvzm zf+AUKr{Zim`wPKE0+++Yl6kY4_r2)w9qa%4%gxF*{L4OV|$xHlELHVmuF^9vAjlz zjlBNPQ$|eIO1)@tqslgNO-L$&Tm^f_{bzAapO{>BoeEKrGXbAAdLprY=;0<}JJemm zWIEdzia89k+o~S~joP$7)_#?%+G6yo(+z7RY%{c1@9y4jLw46`>D1MhpLi1iTyEly!ev`Y@0lnRCyOS z|5z^C&}g#f4s<%DgKwBy8jKMo_2}o({Q4f?w|asNGJ`PTq65BAW3GVr{@Z=t^4dYK z@h#~aOeS+BgVXnB`g|dxe((F@H{Ko6lm4^O?^l2H_#;PJHe@WwV9%z#USM zBa?T9G~1WN$oGN8(}X<$;MV2yU8;f#_q`Ui7^`n&(RhqrNs(b!(<;-rHp?9-=h<^d z{+E1S-@mlt4=e77;1}b-?eHu zUq_CRo(!RBcl(GlGq6_p{#q*Fp3_5;$~IIZHJM;*3WFqzD27pz-;o$HAQR7Bdo-}x z{PZjug_yJ9C~TM9sEU58uMotsbe8mWA!BLNv>rmIVwDuBc7*(?)eW;Z@DcI?_u60`g2Z)FYf)#z$e^mg7^ro4xl?25UN2th9nmskZ5Sq0Np* z6Tw5N4yceO*xA+!*V`UgMiQ)}ZAXs!50!OViVT)*i+lL+(?8NXYBXQK z_wCGTg;5SUwOTt$!58S*`Efd`N_hP`08>Va%27Jkf`>|@ayZEX=;XxY*V!G_I8-84he_>ha~=+=8WilwjR$(@r$g&#PFmV zb;2tS$%h%_m=U(PUMuo;b16F5qX*nae4U;VG#s3+Sj1Gf+;H1grn`IGYx-e0s2mRC zusbdy*=xXxue6mIXXXh1{%&18m-j|F0S|8whYqk)lYTX%@Q+<=Pv0K08xLzLehq)c zMuroMK9VArTa_N5%iiD_ayI{C%Zlj^55#%9jfs!L0`D&2+qa2q6o&;O!S0!cVGJ0H zBz;N^Xm0*=e;ll1_~yVj@|$KDl)QfCzyxQvDOo}XHTq#b+I4F8% zR3VQFrqTJ`-WgIw>7+Guxf_3}OGB7>(@55&jEp61{d$V>%xwb2jXvVk<9#cdKs~0{ z7uu;es})xj#S5pw0zEk#GPqn-Rd&07O}w+8N1uTan6TAVuc68F>nFNB4n$aeE{cCR zSRmVJcYgAH&5sZG1Mud$OkaMZER&cnPv@+T7#OSX@j#YQn|I&rn>;22GPbFY2gFcPufP*4+*!F{M!BTaVMB zePSj)EHPR%N>!0TWKANOm*oYqQwE)@17 z^(>_2u>49cGt#8~(gZl00O4=>1T?Ay1d(=Ce`v8F*;)t|xh*kj5p^bSU`B~ANu;x2 zvnJM6jpQ0d-mB27%-0f&Cz;@v_2%(SozjJNBn87+%i+)5Vxmx?i^-{VOYh3U}E2}PJ0O2P$K z^~6!qAN8!gP2R1f15-+yb-1$Pfi5 znDVtitR>t=z<3bXwOH)eAzC)YB0Z~BfwlAYHCsEZwb{?yrNgX*z`;lJq6xLi7hh~T zrY-%Z)}=RZ*(Lr;uLU~N^tImV{OsH2^TO?VO636!((X?V2Qti7*wY>#~{V;B=f)ow~p1 zeTBYi4)ZBH*IFu#MJkmX*}i9^?Boh z&s?NCaWU_)GUc4kSmaxLgC^13Wos*|(z)Eo99ECBc@m~4km*+h9@v~MT=8i&vrvf# zVOKCYl1MNr4%nLz#spE0n*saYFE2OT=Wh74R{de03$}|3!c3>(vmv;>9)l*lA;XH{ zPk7dH9tA+Ar67 zE4i^+f_YXb){`{(SZDJWMTZiDAuk2=E))nVDAVI+ek{=KXg#& zri6UA_Q~}8bw#139Np^`H4u&3f*u+q*iUdiJS7+^D6~JGU$-94%+2Sk7iU87htr$A91Q3Ip-{OfOs@SUIN|$B zM0rT^zav3{yYV8sw=PN^UudZ_L-k4c93PO^<{pQ@USB4aqqTu0`Oipyy zl`d%iEo2a5?{}J1892>4}1GKZc-y_ILw`t14O-ZqJeN27@vDgIVEew-+F)%o4geDP+&^4*#P<5x8< zr`M}%?tT3sooe;Q4Nv{iYOTm|?rYc$PoI)C+TRTZPEIT^w~v@q$Xywq*K3RM8g9zN zeP(n0A zLjB$#3WbjCb1v7 zFF0~F+M3LaAne|^D7^i#(rX&GzTrcYl;j{DO`>F6a9@7UzKA^F!k|fr&C23nG&~q= zoHXv8o*{Z39Ywzt3WZ;27i&Mq+K8)MAl5gxUTgb(BckMDt+B&i$rhO8APo9cm9eC? z$7#O>@0tqrK%t~wQ&J+HW3-IO71U0b6OqoP&8~MK*@w9>D&>D}g{ksh(!egfuv+ap z1ZR2hQ;Q|kKRr>W-G())-Z9jqB4uK^&Zj31WW%ll#hNOKO7?hKpeb{)4U|0{9YVg$ zfZ|i?uTTUG_@e|88EMBWjHmIR##S#MWPf6&sX+!R>h>K1ScQcKa%BX^mE|^U8-mA(t z(*x$EN&J0Jj)NsqnTkmVW0@P)n_vXdS;f(o&Q@!}utLgtzdOPo}9F-QaM! zL_rxs%-oMt#Au2^<}J7RfN%i9V3QF-VMw|R=1M)d)bNe96wc^xNo2096k;U*+yQ^j z;8h{wV|)5e-_TVr#U%V{dn12JW^H8R+u>BM_3EEj!vGnQ+~M|>TBYX{2Vda z1@meBS!FdYEv&SNQl)ZXftQ{Q*9(s2^}$KQ^F{lZHyE^W@AKy>++U%9TfD=?>%L8- znv^;EZN5w{ueZfo*++y5mKgjgiMw1i?)lCBgg&2v!JI0OZkNwzl39giTpca73PqQg zQwJb!uvzb5vRzzew>KE+6wm9*VlduYYrbq-U6IS;PA!YZ+!UM6Xt6gOi1;R?I#|t6 zjDQkc#vY56Kx`jC&_@c}goj6`dzSy%+L$F?96*uJ=pBol3WsD)7i^7+#E}R_6$*rl znN6aO0D#)- z{t8W)P8?3)@Qyi47Zw8ddf!0{0pUaEAUg8|oQgUmt5n&!qp*1RXW!thGXa}IQ#8->la?K!xcPUFJalxCYcP@%2uPNRo3&D93EGw*%6}9xa!XT z+!_BKh>EHyzvb4KxTY%1Zc1EkuLh$P&WrXMp_{Q3+8e+)0jZEQ)2|b)AT#?d1rEk! zT=x~w7%9a}LF_Ni?pvm|Rqr0X2Z{-W$^?~Jt=47s;cl$LVsV)F6=xUyqSNd0csr=l za?R!Oto_)YiN)i^EBtk!suOXk)3R%D?t2 z)T${k4~}*YIOFppWJd^aTXnN37fu^mZ@WCPbGq!Fl9o6iNz9+jHwtj2%^t}y;)TA< zD=+sWX#V*^t<(njd)b=n!Smzy=PFr`?9hBkf5z*pncbf}A)UUq<-5+$pw83sw02q} zzbCXl9I?4n=9#~K3OT4Vj-b`6&B?IaU%>saKMSNo-cYR9UDIlo5mo;Lg+qy2f#2_P zx?bn%JA^_uLYnswl8=XtV#(`x_=!&BTRqDUW%X}yxtu<{z=B_06YY}%r#|ru_JzpMdiRMgt$Z=dp+HtK~0;tpDksfzViCLKX<`Pu=H+YEp^d}FGnxSSV07fYajZZtJ zcV_M&EP>d%e;KMzEW%=SYJXyED)zFo>-=r;Wv_ziC6}+&wg8{+A#l^?=I%?qPAVE@ zT!qM78%ss1?QGpkCY$Z;;e-aho~&Eo8T>Cz;K^x_uJuTEh(lx6Er8EpO%k=jL!mI} z4}#jcSofB161gOwdzaR3d%dIpH3Z2eB(<Fy~~9P+f}EPfmSLbG^$N1AoR5SP6af=7iSp-wv7Po?sOzrYiTM18NV z8;-)}AT*NF5-2G_6={WA`;* zZvI}wWYu2g^P|X^QrrJ;NL($rt;RS2MnO1#kl)&L2?@)Std#1Ye3FOkbRW69Y+4^ z3UoY!rtQbr2z zUK~c6q&J6S;l4%OExiL;QA?(YZ?3Ogff7Ry(CKyvBT%x0)fx^+CsMYmi_x$@ zh788yiIE{18=Yf*)U?c*(iNL+`4=vfr}V`|$SP7dC6t(l1&y|#aMaJUy-~$B5YewtRqvis-^!Y5(ko5FwidQf*<0I?0u?6 z*L*Tbj)hQg=CqEW+3M{+o;{$g40;jd5kMI>l~&;hcy=Iz9F4{@@>TDlulUSB7;4yW z^;hQ}8ppkLURa~`gNzDxzs*-i_95!gF*K7@gli&RsDh2tX0hep@cj_hI;&Akep2~<9H?roZ?O`aH(#GcLKv1BD#ljd|7&9f7dae$|p0%sATF>JQ zSp{O|?|bK4?I`J?+;TTE2H^Oc1c%uP9q85dwMn43A45x-8ea8@x~Z16TlTt9EK*Ij>{KqJYTi2`}m2?7|DwB0-ee$7Lwubd|=&>9RRfZPb?Veo)U`f0Q=6Yve61-}>`1^=7}{{ukC*BW0C zS2b3IiTm%)Ayzyp(}Hc_0^M>!3YXEvk_skaQCQD*o+e>)AZ@O+4{Rc$7#`g!w?zA$ zK6(s|akwFcf?y@M8L=^$?gl5?MPqYmB@bI@r4l)xVq_v`mTWd^CtnWTyJ;yw>^8eA?<93kk(Xd@*OX+V>Hk-WIquD7A0WSln=L@25Hp3}to z={BPcI}k~64)cJM0K35Pd}g6oaKYq2M1n}C76TSg74QQ|F zq8euLq_gWo2xolPcn6F#{^_O>*gE)Om85Tw#xdgRKr$?3ZNiUIc4qqJM7^-9w4Zub zIOE7b)u|9U^bzw!(3?h;Xm0gWGuff#Q>6n_%#{vAN1j>9UsxDcIqtik;#mZp9uYT z7tD@DRu2fsD;%l}EIds9;D14&9&GvR>cKnq;H@;TM13&Yo}n_y!Rj zm6tDQ5rr9-noKLMbe1^9kR>oW#hm|x3;sns9&y0}!YFQJ4==xwSm%dhaN}V@KE2bz z2K_&n$lp1A2|xwIS|6)h%xRgna!wyh_FlMtk!8&>&>;HLkjyQanoq9vfvec ze9qO8FY5ijEE*9N5)4TxDx2PG+hkWRBkYRb6{*GlZC(`$Wia!A@wLPSDXI6*1y}Fb zn{X`78jDW7i{;a(Od}lu>}b#Ha;N;wwdAkK4e*8Xt@j~G)!F}>7#k6i5axSPY5r#h zt&ch3Ac&ul{85yU8GEDgBr@fD0@Di9PPHEA=qn0?uw^Cc?lcjVw^$^|BvBvxrx=^5 zZ&=Y9a4P>hEbn6YVQB?De!}eat)C72%nJOyb_>jA3i9?TmGNDR!jN3fIhcElC&yB& zMG||z+|E}hafm%g123cPdc&Oef@nOS>tNcz*dlAC8jEp65%7{Ye&vwpfLPJwt)fh# z(rp(VfIXhm?r<`Wnu`JgF-QfoB2Cr`tu~{4BMFq;J5Dy6-f@5}#bT{J*5p`Gt=H8; zmvd66#&P zQjcOpdQfF4Dxz+;YIjR?Fn+STkD_YRAzpEN)JguRLm{2m{Po8!>gx=DnRq@ofQoFk zxG&9rgK^h0SdyjDXfIVDtXI@ErCmnI71xT~J_5VBIG|3S6^TXY6QPH#yX$5?j4mao_kb3EU)M5B$7s3 zK>JTe{>;{t&OBbMUCVR3-eHHmu*uTT>*3kFxy{T zC{N1XZCfuE%Ee;49M5E7mCaIb|ASqJ$8f!H$|gHm59G0x*7xeWSlaIAP>mKBS>XL#aZC ztloFgaZ3Q4qIWpj-lt+q>%^7=gowYYwK1>^u#zyT;ew>GsuQ{0k+EO;KLIUO9Ug}z zLXjrx+S3>cma3J$u%0!!HOjp3rgl`zxcC6A96FX9SB8d+%elmQqwGzO}m0x0p)80h<0 zMkzE(%np0vH4O-Oyox|?>PQio!?%+@R?k0XY!>Sc3%I296xcf_3z@fvQF@&QZ|$y^ zwX6lNTzl>T1w9YDYP8ug<(EL}w|LX;Y_rndwF|Ip%DMo=2zc2VtW+Uni~=6*PZ!D* zf5~QYeYA_sJi(;Oxo3O6Jx>&h$*~7DpYypT1wAl%Zq5crs`7ZeCXGudY5%S(nAcpQ z@Aw@8{KTsDl*6o9;4|_Mj3#uW{lWN+xGu(D=YQ6uayq&~ z@D{5M*Q?4yh=tZI()oAtAfISdYu7SfE|d~f9?ukjlvm1<{;2#nRjx#e1|>H;&}r|} zBcCWuhmAH?iaQY1FLEsIPN?yDMQ$>^8C6G%!#F+`0Efyo6sLN+lnbng&&Ag8y9O{ep0CPpF$r8Bs5m1W7 z<2xXW`nF^bBnGWAv&R9lcFBG@2wE?-P#9AwQp}PSicNiN|4yar6K{B&h8)&l3@+h3 zx)$U9dE$b;FW3F=aTp>rs!g(uOM(m1KY z|9jB^2LTlf1n%ZLem7>lpX!khDMrcNfZ;EJ3vlqNp;KqY53i7+cI^e9#M8KI>|25tJvFsAgwC+<`QJjMA*#NYy;dH;LvguJenq+mG;L1M^ak z-%$;v4CPc#SLi1;w0R>uOS^BHw1}z$NRypSkd1%u$T8)JSX9phSrCk-4;&9Vg*Y7X zDwbbKHISRtTIW7UrOjorLfM2^ZDF%RC(0E;nVlM=qGV`^CejWFH~h8OqGI*mmDh{y z-<4F}%KQ3srU*`yeXkws*Hv+{6=D73A;+;(--_fg^GSX3+w1c0J`dnoeE`KphYA9dT5>cr&I|9P?at=NN{ab^g8lPua1u%p^|E-rA@ z@hhMi#L;ec&TM$+Ko`gKroO56D~bU*FEac(sEf*;wL?Qrio@X?YaxDqq$r1g9RNf@ zWQof4=Y=gsRT->+A4I9;?V@0wlw$jH+kunxvCIJ6PC+rud_h(-YWj8jd3NciOb&+& zTgdR(d3APX&d*t8iupx*SRhj0Hs=$l6O^c>+1-3*#os`_!MdWS{L*Uy(Ktf3&{lzT z0m%OC7szQrN@>(()Gdw?%|SdlYo&f=`)_!2m4XJB6`78vcoD$U{+yZbLJGkLz!p2M zJ7vE5VL%?lg!f}9xF24CK7UIFt5>KJEjkQ;U$@0!td)_iCk_x*$2Q1Ybo`WQbdR*y zDc|vfQ!ju>>iHXt3nptG_;67MUFjG1>escSpx7Y^0!KbbhmrrtMiXiL^)coXX7l|o0G z?Tqn-LoFM#;Jd0ze9#iq%HPDpn$rJ@_Z!h4SNH}43lEcN9=bli@6#I}JX!x5%BPvXS(FSnLO3{dozn%nIZM$R$b@2;ygdPp)}z)M{6Ew!nXmrA?-G&*la%F^oN) zU2c?=%RhIZlF#IJS~ui~ClT^ruX8%Wqu%<}sELR^@H?bKDheaB%k4J_50~ve<=!t# z9}dMvOthUHU`4{oOg`KR%o~UQ4a1d7|AyhGA(qNK_5oizj7OUQ@@|Kf*M3*7+N0Dq z7^Bs0*k3L)&N=dP$8FDZiy$$aSrWEs9|2E8@L*`OMk#x7S;#A?ZUT1WmGt0z{dAx* zP%+fOD*Rugl^qQZpRZ762kTgI{g~u~(1W_THpUIJYH`#2BL{EvaFg2k_Zx)^|C71b zn*a$%6XYMTU%Kmz z4qs$KxziUGW)C8O;3x))XTltaJu~s(W=BQCv6CF~?sG=eeF*B=N#=imoW@VypHbmZ zU$&Q}@DepptZe3I)l(v9RDE2V(KklrGFfPvTR4^Q9{dP-6~nYL zbIdz7)q#}Kl=rZ##ukF?4W&APsY3bB#t}$prFS}+R$hUQt#@f_0dC>p|bOFq3u^`KDSx_G#j#c*t z;w9v?0`HDRc|kwFyrYwr$K&E$!BuXMPP|VBoM!Q4S&U~T(bjp?Ufn)bmleUhKaipo zFIs@x{F7mmc@ZQ1o#8ZW(qXk`+Nk)WYTA5KT~diuL}_GLF@Iw6y3k>7?kisYNk0aJ zsJY)zT!F;{7a)Y`eMr?k1ANs{i1=2!%0k@d-DN#LQl<-t0opb}aju7WdzWA^RI?yAt9NC?w1(4J}?_hRH5B zBSQ?C^2&Z4(=$exP0Yb_X$?yQ->8p9W3y?F<}G^rGR3(;Zslloks@e=LN?F8GyGx0 z%O>IVRwJn1z<7gB^_&0rL)BI57Dd5vGrhiTriE_Dg5?!GyLX@xuBNmGVdf89qygnw zI?dAM*^tvpby{3osm~=Unfkh4P+Bjsp(vnmawHx74($@%tkqY$?C`UfVMTj{n`69z zWjW|-C#-Nnwm4*mJDxmnnxsAuDPb7T2~TP1iy;puCuLY5FNAP5t#^suk!b1e;cIt>5 z2{J&WGjK1qrIvPvWDnI|JYUmsjm8(PwZ_YU?6`dxm5xo>4KQ|twjjaf>d#`LT1u@a z7j;|Du?f9yj4y^JJAj_q6%sc5c*Pkq1;OnWa!z+bt<)>GFeFvbDmXX*EdvR~*JqT@g4t=0K+&Pl}ViwU`zV#?L*-<|&yJ)Gg>#T-T@ z8*Y*P7PS{{I+-P!$`<4H?daulD2X2TH&fPS&V)sR`pS$zZz;0E6jd;&r!bWpdS)*P z@&oDx(N?#Wa!GWFDLuGs)GoBXMM96KIj+!Gr3vkM$@!&&Tb~S0LWq&EE9aq3w-7>S zuIk*aqHN?#N!${DW4sw{(iV+4K=zTte|gSgOdbLFwQP=nXcXNQ7y++~6C!DL^vU<(M43c|DLZ0aDgE8z7$7l|_oC1>5^ zv$WN*{CP};Mly=;`UMjcS!%ucr8g6D+V}HWEK~{q0%>J3LXa?YP#?4lds<4_)NWO2 zE@q9s8{wO5%Ugv~@-wSX492fu1O$(v@cT;jij`00UWQ=p&gR49bB4F=_wO(0=`kMz9k zu+^!x{)|2@oA-FSY_@%;Z4YG~Ig9YLDu^JEkkiM@?6eC7fE3iJL9^}`%Q<%MPD@2m zc$J=C_=xPs|3D+bbLEiw>)lyj^$0-I>8|mL-evHaIb*asY#n58a#y=dW>O#`-SmbG z55{0`*T$T00~N)Q?!#&P>7loY+@vZUt`G!|OF`gO8v^JD55{q(HOmpcgJ1n2j~+{9 z0@0g)3Knh&aF{7(r`*Kr|1k;bOb(QP^ZJ0dx13KaG6rx47GS<3K`JRM)#gO#mNJT)P??3BpMdMfA8Vw~xbyq6Hz(?$w4&JUvv3dBp(0x=E{4tzpwq z2ZIO^CoBf*hC6{uW+`JdkpnWL<5(D+p1p@b)tnOhEXZQtCud3!JCA3#cU`U$_Tz!# z>QZ&-VH}|?G%-;ygT%L9a}e`3LZ83wZMIt0VYBnjFNF;rWwbaFL2Z6!An@Tgrp{H{ zwAhs*+Dk-?X@C^d#TKv3h3WbyMg$`t>EEPHT6gShKdr7zl(Fj}A`)^q(8e*oGiSoc zyJntbQJTG(Rv=DgUrxz1yC2woCZ;6(eAAu9rf+oCc*o?X3W z6C)YwHt@3&>~DCh)A=n{^*`j&c>;Dq76jjC5Hnp7m^+9nkxx<>sd@AEFDD_exG@zx3QX97K(_|vdvk1&U7?hK_v_8N7#L54m zYci{&$Jm9$3`3QO&HKOwiFr_cy&#uTua)q*e_5E*?F37W(0&Wk8g7eGyGDpcy?hR< z^mCW>6VR{d&nI~FK7#PK{4gwN7i|A@7KwG0!E7~Xk79-MtalMid)+tsnd$1 z*K{bAODa|woJ-|HxrCIb%*Z0muykTuvRO!iuGZ={Jy9E_;nbQT54!>N0YiNvxsk!$ zHy!fBbVXRp907y#4;;)ykR>_DcJ(11o!O>k{QxKm_0JCiK;Y`1oWDv_F-&a(9MIV( z8y1DxMS@kGQMzihM|?P_-VLnDElpW5+$XAr5i#=1-L=LW@PKq{>l=`YuCM8?ZaB$P zhqdrw;#NQimA)%#jIj9Kg`I3br0F@=s<5e{u(&kIcXyxP-Zk2-_ddl3qiM}%jU9}u zcMAwc-JRY^YwoyfWVl^D!FtCnXsO2d*wK{N@7%+{a3uw#d3b%+n5!o}&xF2r}5?oq@F<@I%4p zQJ)96K{##I1Kw-pqHdjxPgDWd4V;J1{Y5vSbk{kmqybZM_;XaBu=2Akvzvel3piq} zkW(9=DKu(gR4+v1Jto!Vdgc})IDtepFD-014aV+N%jK8{`eDMT!9X^hLU@2>96=;OPcDH4N^@6fqb_CQrOKqWN9N#ZbT8zl4oz<@1I%u^OsX z?qVyMjbnXu0b0;?5~V>2G+0ljqcQM&j4+eU{`548_>sfTD`~F%_KOxu-YybOs^+)G zEI|19L9l_OTIq{(B#qFbA$rMT_xKljNpy$)tkaGhC>N`lVoZ%Uz(L)RB;r?e_=RjK z8^1z9KqVKhgD=a6GD|aLJLO7%xDrMUA~lSL3Bff*XLpt+VY5n78aouqnR^%^kWWnu z&qTKe3mppO?VJqDco?fobpA*RCaoK z(NB&TqFHEW8jO;57c*>L0Erg|`I?j*yk6q7XZSwOn9E4Xpm;I1wUjpB=`ESD3<6zc zG2$WV3kjI_Icj6OoEvWIq7P)hj&LylJj}V_YqgmslfG%T;qDEJa}I>q>Dpz--Y)!TGgDcr_$3-)dD84#e;yU115mFnZY`8R zs@QwimfpEP$=KC|J09|uC3h->^6ejIxA+vX%b1_gp~-Liq9LIhPS^IeMePqG9y1Ln z<1#U*1#lKWOt>vmZ50K@OK6EFz-&R^928@HEUD^W={prsK0X}FR6j&K=cG_fXGmJs zob${9WpOr{8PFA=J<7mAA*;R&!7Lx`!!*^R2%moNy$g5ZTB1Km3;Cx#Bi(6$j14)kZP}=K*lm!$F^KuHeg}XeFq9S9-Ix-|u&mGMjty1QT)g z!^N!qvt+B8eTwWChFG+iLnp zb5zd11j=PR2_y{`&uk!4pd}H_?Rm$FBahJ;X|%b5lWA5%Bvij-%wms6S#CD2Y8Jbc zxjk9o4VDG$TmzdJ0e7V^D1#UrmONi~qmInIa{+IC-;UY+3=ik~UY@AgRRP;|!FqCu zqwkOB`-?WC$#u7Hhk<0ZC+QNDo?;yGSF8lw)<5RLnD$w04>?^E&r6$YJSmb)7;RpP$wv*a&`|};+2UrzmMCF=1YJ8Y7_(hk; z!tB}fSJhT;HQf1z-DrOSri@p}=&4U^L2kNer2x=y9SECEd90rPhrQn69o_myF2+9g z+Q-Mh=4ast!@?D|FJO!mLSJNw5Tsua2B#^ARpY-@1geUcTi;^>bQb?oI z*2>R7s_|A5{Jg&2Jq||xv0m5BdMlNQ0cBH9t<7=gtCTU*G5ZkT@4YtwEq2(1nJv)A zv=1tbjCyFXnPzMO5Mj;QtsGXb;@=v>bxt_}_b1Kr5#3VpK5-%`i^1`<+C$eQdK9n+x8AJX1=z6}76jroiCH|MCnhqz8< zuwftqbog^r%F%ArNZcnD6Pm2sHZm=+2&8P5Wq;pJ&-w_IChQR0tQdkP>H7$eD{MLY~*DuaZOfJtyo!g`gMadV3xXG|N7( zOohK%I?CH@RR~*C#(G0W#2&0Wy5x>bem=W`kUv}Xi)L|V8GS}o|Ob`%tE_WE^Zf6l~P zSad+owT&yCrER#wdHMPj^M%|v3l6)btXCT!6?AJo#G9e2TwOrX>Fq?)|J~IdcZmo{ z<1$$D0mW@%Y6S*&XYKFSQ|0J>(2V@f3o%SENFN|amSx^OUg7xL>%JtiKqU}yu6Tk4 zWrVQ^GJihl{iyI(@Tr)BVf?BE5W`+widRg$@eHF>e-9Yn*Bs;jzzq2PJfjj!nn7v! zJq)39ecv(NE+l3(eq8goz-K=GY17*F!(NL$LG~_HrXLP;)Q2L<9XRND!DG1#Ha3_k zpBhi{c{*I^u^1w9>iTfDsEh}92Qs<|P~4V%%AD}b8Op5$;+Sbk(vb{u%Jj-&SVe|5B?*O-7X8P57KYu{SHmFxtC~oWxBZyLtljN?P#MSAbAI4H`b-cCLpH8iMJ?H&mE?=_ zaeVWdd$s*&rY)+`^ElLXS2E;TpacijfdN5qz1(RYhe2l$&-17Ak$uQ_H*2!AB7t5^ zzOL0ZyBKE1=km;d%ijY!mo`xptL_K9TwO0;vnL`c4~+4}=SFiZj*IZ5y|Rl| zYK!xrl?A!))7iy?aWCzfonQn`bT~#k^INcEb)vHV^zuav-4#Dya3fWSEB`T@Ycd-$ z6xC%o0sTifg2rk$Y<6fTE%NDkuyZ*CV)?>X|nx?#(Pu zA=7T?Q4*DG>0O5c8LaHaQgYP2o<$uFX8|IhO^Yd4AP!&d4VkSz34Qd6OzQ+4ltR_A zfYkDo$)%{&!qA99vs(vs^c(HhJTyW(w7!_aY8Uxb!QF%m$41kb^17?Lu<-d5fl)jemCZWnuqI$JM0tZydsX^d zcQqhsI`iX5bn>f5{caUZKDJuavVA#2CML{tT28z&FI@nkg8Kv&Jfx^R1t(;&WBoA( zG8+y_9?P%yg$2fJJQ*KIq7qPNzEoI7Ndr8>2G>hi7chy8Yh*tVFKhrQgG*7?OKmh%P^i zJy!>^Wm5@{fGAEFQ3fX82-NkS2su#ii(tojpjHlDMRlWE5_Ju2P|a++L*~Aq-zM$Y z3+Gt0Dy{1ONVvolyW!|m6%;D#GLKQR4!J#P)@|p_kbR7?t3bhq9IDzYjJW{6^a19M zW2QyjDh5vEq8|Qc7!$P4Q}6Y?o_DENe4J#OPHoYNIk$)mRmX_D1cSIY)Kq65?QSfe z2<9$Q_|ISq81C#nqV_(j7&RRePqghvjP=W>epL`3n>GEm&`3U4M3Z|t&>)e+?oSE_ z`ec|tI&o!<{~C(l)4Z8AYJFkDJ*r}L`4c{wyNh<^xvc38p-~YIN0DB0Tc;&;Oa!?@ zQFtBOhkeVKSXPbR~YmT)_?JkvY95`2ykH5b|{WxJMHePq<@5Qpi!y|t-^~j0K$~iffy3t>&RWcwUa4rjpn{W&&kmd29}VD^ zP~@^(l*X8-vXX4(L!YJ7AfwnVnEn3TUFv`0N3_Fbv&%YLdzaIQXK~(-v_x*kaBW4f zOOg{aHCq+oaofj}vpU60opX%}%!BDTJedIlXK3lOw5g7Nank;V*5GebO(_k!qumnD%;+0#0K(1~7;dW;K2D9FNVC?k@gZtvSi7l_i6PXv-OTY%hihw{>YcX?i8yync1svyfF6%f^OJmP1D8E{?1%13ILlzbc-?RNi zn9%A}W>vYfHc^o#cY{^{T8_k(_9YBCc(+BBrGcs0#Tt$w^qIPwWdqGShoF&F$$V}x z_KPuhlTD+EG=dH?k@|hQ(!~g>Le3+%Db&NQ!86)ocNuDu!xyG=FCWsK-A!p~79}{^ z8wxccuk9}+KkDk*!?*FZGivvz>#IZ#hH{RUgTbQUFSU!^?uhv`2*P@QXBD!KS%gV& ztfsLu7-*;)=Mn;v$)hsCwq|HytuKm)|?zAe> z<|L+H0p8b<1ulr}IvMhF2ldY=>^I(u-v3;uI#e*c>O%Z<4(FSvd-=KIKLzo3imw@k z@AWF2|C9=U0Gey&CLvuh#cPnwNV)HS$M4^Bh(`aYjkbiJlc}8gFVXogs1_m!P;Li- z$#W|I2NC*5jHyZbHDlMHe!@EWzr5GqvGRX)G$Rj}Oa^J5=a#D@Q4T@Me_2>8h#qQ) zXxg{DQ**8pr=mYV>9LpL*@qoyr*Xov{1E56MK9a@Z+`k88L@{LAVA-4HlC+W5aEAB z98P61>a=3&KLBI$HV|}uY!guX51I4#THgREx+;?7II`44KDX3zol(F}hV#KlGL^bB zZy+H4sM=~${ZJVS+Fl|@qg4^#)OoWRMuX~#K*DDeeQ5)DR*~;uzMowPW;DR7r=Phf zBqPygGZTk2~>a zO9H^)&kA)~jfrEagnV-rAoF88+cX6vUW^Taa+Hl$>q$4HRLVzr4r|YR8*Y2li>+pd zX%wJ*hm5{^Iw-3t(cI2H1c*0Fq*@nWz1^yG+HE^Moq!b|g+Wygxfcfi8rQ2&b~FZ6 zY``vHy_YZV5L}~F<9SbaF!qIhbGYU;j?lwgkpx+uL65~_iYOB>!;lKYV=cTt+e{DF z3NjgtEl2}w({=zuu=^GpgF2BKSkw>fXJUEO7cZCHcnOd8T0L3%ty}=K0mxB)U8j`2 ze?Qf=wrc{KF`jIFR~?Al0i>7&WX7SYpO5g3!kj+>qN5wtZ9p0e`}bubSmq4xltDYK93s!+7&i)>D&EZ zx44EO}qq zY^zh|yJ8G9rQJ~zet^s7V7la$~Elq;E0 zkUISrtF?NAhtK_hba=MV%8pVTAUNpTu&^0FnIbh1Inz$$GapfwkpXbB%}UGBs@oc= z$j@)-n4GF5pSWDI_5fa}!P8kQ#jzwcD~yoA3UC8zk$AkUb!l;Kk>u& z-$cfg*{x^cXQeW^Ags|#AV}u0({dTTX$ExFf<70?w~u6KO3J`@`u|5_<;*1Ugg+C_ zj){fQZ|30T#Yj6uk@Dec@W-0w%1GKz!%VVo8Iye08Pl4+F0kH34 zQVr)YzA95NNK`Cn{-!yR%PxDBpGr`G6SU6T2-pgXW*5yNfHOh}Z^VB+XJ{+I97;I# zd-~IS+KQ)@u-Q*85p62ar&Is}6)gS{IG(=(q`!cXhga3wpM!Bt0zlX~<8-E$5_-D{ zfCYNZzTSWz!L&i!dWS?85V9eY9FT|R-|!uEd(vr`V>#@vciszcX^?@=ggx*62kDdm z*eb8r!^ueH6nSKa|BYl~h83fDxN7$}!G4V0zj%#M&5g*c^m`tNB5wSb^0mi*kISo# z@CItD+GX6l+P7b|DlUDDWHZ2!a*OimjT`6j;Pi_Vrg`B)@o&TDYx*w=sDxZd))HE5 zv6ven&tu4&n@gX&eXB9Q0dNQox(Lbp+beAJB`hm;MK+ec=+503{Ma$C(28+Y-`z@#kS~iBIR0;7ZrmG+S8wnPa=~Rvp?IPZPys0+ zzG^PJO~y6jlfiyeLS#8s%_#YCML!W{OJA{Q zM7~DVaY!V5I0rl-{-s(4mqhF=tD06@OZr3)HG$sdaVeU$@ZK>Ujc|PS?M0Q(qlSUC zP=ep1cg?P17+};A$e(UaYt`!2&a_x-fVKCQU5TTQ2=`)@@+1JZZvZs>a}8uUU04p* zD28UG7Mobd0szshHMu>IDQ@{H>i{y{sq_6&j3TL8q}OD~U72s+M0J|;XF=a8GD-SGS{0TDiA$S{Z(KKzqRc=9FXZ>TPvzl0 zLsk5itpuP@a^qk(WH*;u&X+xQvcI5Dwq6P-m6{qY-c9g2XtrYSdQr(`%%st$?{dHq zQk_+>A8p{&J{bU)1|& zw;^irKcW9D5o5Pk*XlZhUF~4hr_igcA|vg<*~(~XF#W{u_uDuXViCp!nYEfI4do5) z<>#VBxltUS-2*X?N|DZ!`grLcidmk3v{L2$?9WP6;5{ef<3#~IS*)o!-nWN za~#@Yn`g67`|}}${cgGtRSY)KEv9u>SKL`XU(M@F-aVP~wJwH@X~JoVk=kXYa@(J5 zY!fVg%VPDj2DH0Uv6(l&H=Z{)*5JzG0e+psPR->!{2V1d1(?tC?2a@*w#}c+uE_8W zh5heW8Sia06|$+IpWt_gd!2%ZD@FUMs_vHcdfc(KO5O3CjE5~Zi(3p$=FJ&{-P|tc z=nAJVaXIA<<$kdci!>U3K%39ou-)u=KNk4;)9+sL!^vv1{g1@2Ld*0G<_gpUH!d`Z z%&;%XhwvB!*qLtDZ>mj7n}7;B!6nb_@~!{##@YxgUP5Bhe4<^fT6w6FFOH+`j86Q;2gwzEa~>^l^L%nfTWP_RmrYzu8W2>`s%Ii)A;* z*m)$X%@Q#er^*@5cp1PhMX%96J7s(w&|);(f7XnJO@>{`;`OLV87CqdBV4E^AFhxO z44A&Ko639mz_;!-d=Zkn%5~5ih@fQ%pjT6L6S~{+7wO_lD3gPR+YQxOKYLj{_LnQ3 zQ9hi{l(IJEQ89dKji1yGVO3z?vHmq*YOU9kbvzE(GO!;p-xCYKaEcGN$ZtFD>k2$c zyaM{x;GsC(caxu?xIy3$h45RJtd(jE(B2{zEO<7NGQ4!xx};Z{r&wO${y=uSZ}8g_ zMFu20YhJKozEBJsCZiW!&wCPmq@lE<2 zNLF}r)Ydvq?`!bRI*JhMlBPQ><#oL!j~t4v)BxV4Y%FXL|$C z5**bZGZ{&l=trmti)@@r({P6`?X@Hl#JFH z;`m@Rl!K#{M%=%$V8+=r8}0(9L4>1?PCI7o$F2$8y4}%vi((_6BW8W=I?psq&x0}K zR1Qb&4DhMRmt7@3l~iU2cMjiJaP{#i}*Bh0(epkIOBw6|V;UHdFb^RGCZ&fo_$sWXSW}?Nis#Zp>=OT!Qy2 zjy^JMCBa~pU%aiv)dG9-+%5;5jiMlT5AI;&Hj@a)j}dO5Tn5 zXgT0KoLDhmFoBpIrZ=+f&)KTa<6^E4h}-IVAJ>kzB!yCD#0KGG0@F)04en?7Lrlxcih+6+LgoFo1M!o1Sh+|=oDYe-e!jGr(vY?QaTt2E`a zdGQ15ym7=FmdBpQ-+fu6W_~q+Z zwd1;Sl#Z6lRTK^>Wpcm>St(Hg$9EhxsnO(*3duC!l@w}^N_890fC}6`gF~i|Vz{dq zK4F_ZLtBlc3$f66C>92PR}Nc4f{Z9Go`Z@!hY@bBM20MboZFn2g{=VHSwNuJiB*&s zT6I0(csY{H{ROIR;c7jSJ-kXXxc%!aI+DmfiI6v7f+8%{X7P?Lw;4=p3?^X`o!Dfh zniYP&r#(U@Y|R8W7_*NH$TMupC{EDaP-ut2mGKbT9@n2*!XSF-`BW^G&l=JQNtqhp zUNNC`KIq5-gEw3H9o(7J2v1jDdb86cb{UYvg+eho>7~Oj_M#vEDA*$x*4JrT@_>@Z z`pHvdt?`YNsCIM*f%Ya$7BZZ|lh+pM)bUqxSTd!;NJ!jZgxxFxmv;G02oxBY2$+nx zs9IIzXzIkTv65`|P+tLh9_KHzHs%H(>2-EYdBJ87)%(S|`XQU15=@ za#v->yyXx=iZU|b!Q(BD7-H!4$xN5@uPr%zR=_&3#V~`asG!5B{n1)DLIwMNPRAJ4OaL%@ed;u@_jqr0o$|_E* zCJK2zyyrIj3W$|=ndT1>R8Zj8VN0GvE#bOSx)Qfp`dT;M3=JDbfEF?Dt%uJK z$Kn+~T=ovWabIIC$L%Vn{9pIhm{oX4!K{`Wl{WvCGrxslpFqSrBA7H{Hzu)Qm^hq}Ol_*vYOFjWa9IiSdwC@6MRu)IxJ{TMQ=zi<2(KH z;YH2+`o_Upcl-D6h%O!varhG(VNZA$O=0ineGT7N194~^|C|}Mw^LJ(X0QD|PYS&c zj)02INec^L#lvIJ?&1eb)V2%seoRF}#!CEqPt2%0~_16~S zeCa^{!Hr@`9!yWLPyrMEdY?V#Tx-J8_6?o&-oIif16}&39Qx%CR?Nd)iXXk38W~f; z`IUfam5aMONFjV|w|6iwpzYxFv<$;Ik~w4X{Ex}BR$D(_{+``+e8=VmianWO()-x( z2J!cR;R1FePZyo$(_!ID!}H@g7pSvbPx`*e0qjCB_s9UN`O@pRU-iLms-C!J6Damu zqw~1E5==S7nDeZwg3s}QTMp<2=ufx<=SEYd(im6waHF2pC_5wn5^~8*!;_)tyV=JH zGNQwTxE9&|neFkI6>5|afO@TkXsTAV)`XZYTrRQxp%ds+(6@9o7|yKLRt$Uh3(AA# zM#s=9BnHf%k18bJi^aQQV42Kf_pu^I4lDq1e|+*>r4u6zmw5{?hl2G%ulw{u1cKWu zps-l}_!~2jglI}n%UkUZh|-}A@@5jXrP0`5m(YWk=o&fRXpuo7N?b5-Ed)QHuEoCG z$M-4lxJ_nVsOz+WnHo;*nEe#!h4`gp-vrs#gS_C4Y zkD6p2QZIb|C5@!8LIOtMy^t&iD1?H!VK7172$u-s!1}ZE!s(08#I*>y4?INO3)u(d zHZ6wF5J-eCA7G@RP*??z5vk-DSYu=0)Io;yOVfD)0&bC&-beRVMQfY6>2p??;rgAv zn571BsKO30>U%Mzgx~_G-+vPapCSc59M72#t*7z9^xvzJwNoTkvg<7G_8!(M6g$f1 zQr!#=F=A(pI0Q{s%!uzWPNjR63%L ziNdeA^9_r6hHd$m6Cy{sOp(rV7_6BZh-~*n3-b;4jc54`T_&7s1YRPTjt07C9C6tT z;SV|+9KBFZa-GdCj^4B!SV8|X1_u8WDN`J`5j0c{83%HnlaG&XEGD4vEz*D+Fb|a; zhg2QN+h10uDgFMO&`YPoU7L`fn_-m}Z8o09ICatO^MLLyAB)KoNJZ|cY$ibWMY?j3 zdG7NDfTQL?_xCT*r837YL^JZE1P_I(X^oN3pEL8 zXVdL8MOVTZST^F;yPDE;NF8A1iWIGK?DZYF0Y9V(A!yhdiu~#I=LOqedK;GOYBZZ4 z)_HVi+N@~q5w{+te3;=17pd0n8w|mq5_~1HeWmZ4oIJWd7$!x^KrMmktzo{GK+q#> z>sut5U?BWO9`EI5qfK^ICVOG*u+Mt=+laf=(^Qv~VWO5sn7q&-%3iE=&n)`Pwe8WXsfj;f_7W|1v4e@6c z3usr%&iP~(!ac=HV6KLaj?NtLM!r;zB6`q}-#bEZNuX5M8Lt_SC-MB z8T!R=Gxl8s`TFN~zXzk1t!U@gCwn_|You<^n+dZ}I^)r+J&VB;M#G?OYf@iBbGS<} z!A-=GJjqoCyr0t>DtQz^B4$zOesI5A41a6g1!o|%Fp9Z$6}xU@_jJLPN~?ulkKGH&>vU0xQTS;E6yhW0#Y`Vh)m#(l zs%S-ge(&D*m7Hpq8`z@t;{h|Zl^8kJnW?85m%~~@1k^qKqAm1zzJNbm;Wu=RwufyQ zH|OcHKnT;irRf3Ikn4WJM8Oq1@TZt1BOAiU zqTUlUtoWlKWSDTtmn)HVG8YbFVLx;uY)k0pk9kZJ#H^`kKRTFo&tY0o&mg3m!M{r^ zcU4y-OS9*33m6iR_zSV%5d&6XJ%)=J`p@zGkHmyfECT!9dwNVz!ap8LoLKaFyveFv z2q=Yrm2RI@ms3@sv0!T-&XhU85^77gwaeL8CSX|0!l6NoLV(wMH8rbUkW_K(;g2G2 zRb4S7LbkB5D8c4T{~|%7bj@f0Z*qAuzKN)f$Quny*W%u<9HZV@9NHoyB z_?01K2@9d*861ovlcvj(psg(?zZZF+=+1LdqsiF|) zkRwqx?bF5=N3;;V%A(>qgm6}cBz5}=gFda8>SxZe(;vR0FHw=E(5w)vV`k6z;^l>U zu*M)6IRr{n*H2pT(z8TF3R)FKNFhY~*F=@a$_|CGN+7wCEMA;s7Q5iQ8$04KyY?+@ z;1Ku*Bam3X`Uj95s_=Z&5tMKTo|uHZ9{LO`UTOXtl>yXUGws-cxv_Gp9Mh+6w3!ij za1d!a-1cOAt1m+srWBHaEgc8?>+Tu>FDn7;*D3T&Jg$j3nrV7b$*Tl|6B^5x(j~HK zhoB|vqNv1K9*}Qte|*?pMz4!NK%U-obA52U(Qq0SsDN*QZlhi{jzhYLl1?mJY*-Lb<_zG??j|zm%gFhX7l*NhD6ow(H^)W$enW$a7PxkZTVkoq{GpokT z@2ke|bhi98a3WDHz2!(DOew?=f7k}4+bh!4&@eRF=`LAR*nzW19;V8tDRs6&7oY?+Fs%n$!v>2#RpY zMBs|0p{`(t*8~{m!1D2EF-WqofQ@JnwAkSNz8A0&nf;8=M{1wKq7EhCip`-iw(uQp z7my$(bJ0kl;DQ#S0*x{X^^6GctnDp6QZ!`nkx*p0AxMHbSa&vG|2-|VVoIqba6aHV zzoLUDWiBi4#kFY|U#^t{QdJu-wI*7>q5*8dWNN5bOmLpu^Xh$R?U+RTL(LK=g%nAN ze}57gJcL!k6|4b|mb<@{7sog!r-m|q)w{$S6o|&+4CU{ggKd0U{zIvLV&u0Hhx4(e zC-C=x|BVs~sZKVYk0?EvMivn|{xK#sa}>)QAp==bU} zH@cZApDKdvjgBY*<3D!+Mv7E4gPgErK;V<{2Rr)@AK7AtT2Z>-z(GGo(0?%VdBQj% zAi6I^1pFA0lI^E}0(JzVNkc(luw z&jVL<1#IQ`e>*MZwtqA&Bxx2fJHX*VLZquiHKxRM<(4#;glWlrZzAZ=n!y9EnDh;9 z#56jwE;8^(9Z7eu(N5B}X6h9q=2dKZD2c%RKjVi4+;PA*Gk31EUj9k71Rnz;RHRb; z#~Ss>X-e(vjf8P@#Z5)A3?{@VR1lKYxyzCCFwFD0)Yn=AX-8?#f$91DJlNg#!X(AX{=Asq9S2%q(%jwFxVM zzk@Vbq$$cuttnH^oPdnIxBZ;X1M?|a7xVv6_0I8iMO)i;Y};02H@4L@Nn_i#8(WQS z+i7g8Ng6h`ZG5Xe=RCjn`+p~Ut-015dyZ?|;~pCw5AUy&g7ID@=l>p=lpF+Wk=w{o z0v11Bo(YREt0q0=SJhuMY=A|ffsv`L0WDfasuF~!p@8E&HYo}dL_X#$T$&gWX*5iX z(uipPWFOg&5GFFtcB5Qf^ol11PNAb>fXO?Lzl1;K7h4f9IsTTO%<9q z%N}2nGfr96lmwYMbva1kxHwPv@3oc=5K@$C4Gvx!0+xXB`U+klfyMlEK8|2YgkaB{ zyrI@LZpnn1BgOJGmiBKr)*$h3VO}3`=cU`2-!2^>U_*$YpTn&S4_{`w`?p1fev$PE z++Ko)#r75whS$0QyVW~oNkcr`2B0i6rdT3DWpXeSMi7^-Lm7B>X9E4`+k3u8EGRB~{pVmhAi&Vf6W6YGVcNSrhy)@m)AEc!puw+8#5H^D0M|639u-rdg*3qVC1$3W>vj5uSZMUEa>Q_#uulR%(> zfp+v>aSmtjlO|Ri8i(G+pJ+g0{iOIC0R2H;4%y1tWD$EX>PTaj#z;9Ti6`Sxq$XiD zZDKxq^^wO(37iMz!2H`3LH+_TIOCytU2>?aRz@3Q*Sse;^om;lSzzwC~IZ)#~F1Y9yD3KVJ9yIyK-7Pl@h!ypK?0WP7}dFA=K3wZ(w{dF>($8l_; zNLUy)sq9R%+5JaIlbpPKK|xY=DKv7<*^-l(Nz4b*8Hd>xUecJlE>gWr14ZI}RTQNr zg#=8Y1jMaL#28zagF5lQ@5dzhcZF0`LylY}!D3`TMyaRO$>PJTR4YJ!b6GrZL+C*B zYH87pZw$k=CNpg99x4_b3qr?cO6U68d9FWnyw%E;R)t>D{IyL@_H7|MsG`VbK zBK}a1yBtT#@%H4~2jsQR51iAi!&yO+TJN?5CfzP>=UaL!M^P+I4eKmP3XO_5ACh#M zf%q{XvXKZ0ZE%Tyr=&(< zfDc^Od*|YTFaPQVxBYf#jb2T)4a-a(_|E{BvvoImdV25cM^eK&k1dfW5(Kb=w|={U zIHEY*`IeiLmWu~szU6B9or$zx@FiwOHjqRf5AQ$1U~p4uY`?qxu2DOiscQf}L-=Cn z=j1ed*~|Z{M7F_c8db4#D=-mG66pvwp~d9IR}#8i_>HH(ik={8tf-b(b?Q6;l1CWj zOLiL|QvjEX8^1kW;gr0u%njcx{zlgh_Wkok2URQ~STh`wPPv%D{O)KHVVCu9F(R7; z9SV!%kFKaT%A!vWIAwo-qiA6ct&~;1N~Zk#m7$;lOJgg}0lekXaQhzRk}H?A%f;g3 z;+Tnv1s}tvGu`Zdm)?7}@PEnf>exO1{b635m+_}0V3v{Z;~{RT-^JZ0 z$$R=>xZUWOh;^sUN5D+$DmK2htRZ=CYA-=hkC9GxJd?W~wnVi+6B2p)rSy9nDuKhF z;y)Y}YB+2Ty2gd4lUg+yE$98z*}s=9&Zl8SQW*^78ygb?CJ6Z)SJtQQkMCB=L+=BM z6uD@VgyGtaOq?5i7PnU2h_@Yw)-VB^yjJ%;s>i(<&_C8^*2NR*0iLNUDOKxWWG{Q; zZfx-yfQhiEXg{azGCmGYhs|OhFn^nvr~Ec)Tt2@Y(pPLt_)_h)=)y*Ua^CT)?Mz`mIn~IL?0}jkUw`1}Td4({Mb`^ZV`I>OfiKqxP0SNIULUU}XsE zK#$%L6?!ovpzk`LzY_hD*>-z)1>c(C(GOU?OihiMcW-W{%A{!{S*_hl_xJK%togk@ zSEZzteM*tclNqd!pn-fHF|1qSj^25m^qQEQe9G?+JJipSSc0thzL$V}5i-ml$G25F zmFc9`hH)Rp+DF#eX@sW8tRiNakJd?^1kLDJD|%~gK>A6!9>(f%_o%|ZM?Z17Lqw#1 zGr+9nkm=tI)(Mk*^U48e*xh@0`*U~MPUtWcFZfuG$^Fs}hJ@1d;(^y|VvQcl$p&fX z_9Ewf6<`Atnb&NyOmi=9NY3pwR+@p0G$6s6%!+KAxf$tocDhdKMCEF|I?=n%m^`^d zK{ZgQxpz%{Z#R*+h5W@NvoYSj1GRO_0UOjq%avfQ(S_K28<|+InpS6poumA%!DIEE z<;Q-n;LF~Lnr7}grjPcp2iS?>FuAaYPgd>07xxGPhK&|fQFe+K z#NFMCMg?0ntg+c0OMZ_O1FR-;$lb<)KNomf>}IQ1^$YP{n;0NesHzLX^O$F6A^#{z zk{lllvGhHE$?4Wma+7)uC$%lkb>2s>qp?Y}K{zr5ha(x2l4$(j{^3_gH;bF`o9*3=1Fv5` zQ2z#N6j=y4@nmkpPvu|ft9%LvSlWlQhV)=FwnxD;J~G(NUe5a+@E8arDpDp&l?#;4 z4Ht}A!QF8d8FIcc>)CoYsZ{N1{&Yl#*#B_h!yC3g+67#|vk~6i#`H3VbwTbG9_G9R zykFNUvmAGLL_1N?UA;F#_NNDi-aH_4Nb8V9gg>U^ocuufqhFe>yJ&^yi#JzZ6PVjUCMSf#Ku&tkJ%pe~{N$npW+X5x0dk8}|sTrB=o^c8puVuN)bD=X@j&Q(( zULKC!??+T0wan!3U|aC)Vrp^>z<(02H0`f98Lj?i3TThs&};zaP3vaO<0sSWKK?Ee zJ^bv~wRY(FTKe5QVQ3W8Bm`s*#J17&NUoIMXT-+*!xm=uARRCb?6kV65B&_7J=Iz$ zZZJN=4OdkYY7(v&tU@ z2{CK?HP~D0fc?C6xrgY2!FR!j!|ZK%Z>?eZt!8A9y*hm;yZ{zK1q3vTAa-CV$tjMg z_qNoi@6Kq~49Tv|XYVq9c_$KUYWk!s&K}19hecudA?lU4NO~CFA9hqQ#lcTH)<{<=>-eHISdqN8t1&9M4zsS&h*Y zvShbAWAfPz7gH+4+&>P4wmdIKE}B1W%^k$%82*y%X+*IIWl9ns|LpzrY_nhJ_kq8j zV&P_A3oWkR?d|$|0(V;1UhSw}ILlJsH#8=z_ukI;9aLXOo5Zd9bXlkVS~gq^j335g zkrPUa(?YRAG^1Fp+C#wWs@Ug*sv=p=Y!cO~+j6$imQc&!BL>r|MN>=Te60~91GAw$ zY>arO1bufF<(zgMg{VbVEvZ)*0J*xvf@~Me5|IX6JUq3{n@-GtDSa}o*L<(v=h`pW zEekie!TKG_I@bO?2=$x%yf ztyviLjP}^p!4pdG8r}pJe42d(szS(x>B)?! z=od9M3+xI6IOi*kw|-T4*O9z2R$`mfMY`*Ii{TZA|T`GABiu6JNc9ulG_(% zzU%hy%=7Q4gToDmQDV+osMo@HrUkcXG5@IHMoeS0+AACK_W5i(37y~Z2$dd%p5r^Asx{1}AeVf5}wgWlz?df&5&P#34GW7gr z)4}Fd-H(I1`b)bxi6(%QKHQqw?_SMeYq3{HmVUB^r%(L)sh__}0E!BofB@|C6<{*j zDrTur^1&f0#NP+k?rI(0+j1eW8*;$Ew$kcyaXu+a9gFL@b?p)?a-jxVe`Z_Mvm^a-IqF5Ae%}+7PD2qbk2Mz(8U6aFTtKQqAjkgqKdt?SK^W z>-gJyuhcxRAqS?mEcmZk^n*<_#h$SYfhsmFLL2$g?EkSJW+I4@V)N^}_RkY`eSS+) z0aYk)%))io%aP|&y28#`LxV=Ey8ZzqXfbauuXp&bCEmOUjXd6`m7ZGGC16ke!$!7* z0;euRz{=@1_O*FTPiNW z@@DT!`Gy_{6FWmG@Q&^k#lGuEwA(%`~;v#lpg3rW0Z1 zte{c}I{;n7U}v#Pj$$5GtvHQnUxL-3DNyS2I3a@hTsh866A}`PjLUKNUQj~I>MZ>q z=m!ue1~6k~6;01Zlg3RkCIx?#RSZ<3UeP@j)kdlB-lf8E`7%C3w=#snyCDXmB7IItoxCZG*$c)9x6;5Xb6GSB&Su5g$E)rp9l{g zhW)_<438EdQHL4Fc<*VPQVkm{X^s5Ny1foKxf{%alWrIAnUdO%Q${+5dY+x_7E8Qd zLSu8jq_@%Bx1AlYl!pB8=}Q?ygnhz;x?H?SEbML4bjp07oqt>`b;3&Gy6W!jQ?=LN zDRB^S)=v~6Mg7nvzhuZ$&m0SDh9I_?&C8LYt2IbU=h89Uj>exCBSRvXJVuO<4Zw)2 zQ{K;NcVAd!(tqqBlCu1Ytz6T~IIM3(d&jL^Z&<*UG}fxiS*i6$o5IkUp}OLCsc!TU zx+DoJngz?WUI&0avfZu3~yKM!$E`QPO;LqUwZ z5KMmqxe%5$)~vk`%Mk_5I1ga1^W!Q7Hx z&~$k(vV}O^-a$nK$<<^g|NhWhU}omKkNM`ZphAVz99lS!YGel30D!fUo}(lA5cc=* zkaeK(5*ri)M)MXJ01Tv9$ z_GQS#-IrP;V^@DLh8B~&FugZ z&{|~dQSBkgT{1M)&zZvE1Um{c#2X(`9+Iw?+7{+S;I&VVBt>)h*iv5dhMsjF$$+{# z`_%=>8IjRo&(TL|pft!SnhH6>$Qk)bwH3rJ42Xd#_=`1=>#i4Db3iPHx3gJkM#f*R z)a3K&PyT~KqgzN)-#mMFpQCG(S9tDNO|U$}WQ-Djq*=_B5T`$VGGjy|i}QR^UMBZ? z_JVA$+t2R)e%+)r7zy*4`4<;LWmrSQT)oGS;%O~VndnR9Q{vm>J7TtlrMSOz@jqCb zT-ZM~A9gMNky;zMg%J9E3}Xu~o5#zd#FZf~U#r%cVV5TghYh?C#le~!>Q2mgrzyj2 z=u1{jAXOg*bT`A)KH4uaP6UdD0Q0^#&*#@93#a5>qsT_9fu}sl)PYCEh2b8%GVDa7 z6Bg&^fp{Z{+dxU2p{YO6F%4@5E(S?>yOMUx4!LG2&3BgHY?jK~FB$Joa9Lb=P7}F^ z5HaA;yLWxjN2loN%r8eqol0VRXI;$$Fs_R#I0Lh<_wifKd!^eOsA5+-Y>3hFJ^0}+ z!`%)AoL7QSd*<>|2yb(^oE%OQpMEO$1>>pX&Zf}|p~olImfNnnz%13%$idJ+*Es!s zAJ38Mc`YXN?Zpr*hB`3Gp&wK(RMgolh71R?V{qodw;(RXj9PO0ho@m6OXdDAOtOKM zJx5^$(nnP>DCj+s&m-^C>FEhl{KOLzOzg4CU=ii9(I7`rBo2(JMlFKwr*0e^x}cv2 zNBQT*3FMX}nE|Bo76hEmU4w1*vPnok2wVG4>J7El9f*SD_1g9EmtHtfY zepiVGiW@4Ouk0RwkL~UdQPH22BxL()xc^~M*l>_36N&RgDGD@KFj>C)T4(1*Y}I_Z zJ`o`pL~=3k-kA{&fPcUZhd35T9c`s6ma(H5Bz>JVffM!L#!y}g_~i_c*kF(;>5KU; z?$;NX(o}9cOeEf+*Shu>pp9yI@p!-Lg|W?xSy3u=hWXkId^kUb;5R%A_mZi>eZay+ zr$C)#i&{(bX(0#&YV~sMk8gP4%=idz^1U!|@+^={jPlVaQcp1KR!Y$9s5fGKR&A_< zOF`pFj6+pSlX#0;G;z#%2D{S|ojl)`bqScU$mHYrf7Vi6?{p~&E%8)*Ml*PS&liyq z_fIvH(a}i9CXKsB1(C$~sN?8_%wTgR-~J()Mpz}**Aq0uyl(~$Z%q2+(*d?2t;S_K zB2~n~DnT}}VWlEf_P6X)Mkjj%Ab$a{kubMz&&Wx1-vdCmS$BQb9{U&~vuL|!pm9ur zU=M?6cv}-9F2Rxw0*2HY0de& zLv8&}oCN@Z3-yueTg$O*naZU9iycyEe_tjllk)~A)0-8-GcHMQPqx>|z_2eh`2HS@|wf$fbv%y+k`x8@#rEnE-W z_nHaZIltFe4x*ibcO@q*)bU4jb5y38M+u zYg8BDj_*2(zqGgl-a@-6D*snMj6(TNp&y~|{!NQcdcCd*lo|0oi5%{0Aai;yDQ%vZ zU;X3L$paSQ%a-25_YWP%Ztkm%@4$3j?0cN<>(vM13jue6?&dz#u#Rj2-`3iYF^Nba z$VDZcm8Q-9o7S726C=3@vYIGKQozrbHI3D6QY68cDAt`GorCmmC8LMrzjYgw;AcAN z(`iGlEL{1u_L+-3FTOWhdx=2SW`bjwZ=ix0o^5#r1zVsHF^^uyuSwn>j>$|~VA5uu zWG{zD@cbOL`@!(LlgS)EgjM1bf+TXC!^!&2Ca1LRKTE}yUEne!!baMoXf3PDl9L4@ z29SRG_w6KYB>u4i2$;lyR8&`2{8R(%=t-Z*f`hrU3^1ZT%Nx_=a+6`>-!_Jd)R@JG z$k;z!9?AB4x6O(t!I?N*7e_aJyCQ>xj>^QqAV{E84&j`{Po&YLVWt_mnd+}&p^ykcff~|djSv`%ld5TVcsi|~i^2u7(uH--$RedwE)8=iAhPWLP@G(N`d-_2AiPgv*XKpf0X^s?XT~hJV~^=k2@tyk_y?~hrU0M zVcm;e6mGT`R*S6Gx_p(-?Z|@u+?)pjIc`?Bch;zpSJ<+$1cP>$FwSG+$*MaTYuV28${Xnm42@-iVO`3 zF{o3m-iQf4Uv8W1r)IKsUpKi?%AwD|emBH9)8s5yE^rhx-rcJp(sCm<#4q1U9x@Z! zDHv%g0$R59O9Qi#eiSst60;0q)Mm5);h0bGgRNj(HCB#bbKS3LTrXPLJ0#q?)Auxj$Bcg6@KZnoDV|Pr<j_!u-SsM`sbN27a+-$dV!E+Y#sDrGR9f@1B+D5wtbxYDCz@9Hz2inWoQklk&h~_Wb z0|-@*b7)ld^VG@Ce4XgB`D{@C`{mV*#GPfW=PQFweQ8orQ5=;eex4%iZ(z;`$N`YB zy-CVJxLqt1F_cm$R)eHucsBa=8) z+{96gf|j(|#wQ%GS_nC_c84+8-2?V$07d|At=5<9ZcP?H8K9}!;NJ7~)@1OyC^n}n zOlyIzz5J0NYmSSvTCHGu=1Q;2Cln+V;?d-!_%1CQfN+z#jn7vNDXn~-*WN?77FwKD z-PZC^!Pj#scBQe2qqZAf1G`t)9hOpY|g6A41{=CU4}Xnm&H>W`^}!~ zF+P$$-f!-rK?=4@^`RU=e{O3Ky<9E9m5JH9^X7om!27+NAU38;$gsy894t^sVpd10 z^qLyAGK9J6=^1j9*u6Y9)=?^Tc5_x)xa{kCtBu~7C8mM>+xc0bEYeHH1M#z~T@HgR zl|)Azp(7xngt<&F=>}6(SB>pHp7xKCjBk-S z53aqGvdhVBw6Jb4k-oW(z9!B4Pa&xc6x93BApH?!U|8SsR=~*1W`Y=h`%uAPH2q5g zLpOwEv$qGi*8>-rS>vHQS1uf!)$26Y*v>GfYJTxTp91 z_QU%l5bQPDJ+O&kn@75RK2Tq$^doXZ5KmN~l^dJtLhL+`(iyZ7f`O?Mfuk(xBgb31 z#&WZ>y+l|8Kx+8iyk6^)Ff=$AKBFR~x5s_&1v%$$ZD)L29F8OwU)RDH-uE(dxdASX ztQDsFWif}FnS^Tvb2{!x@kgMP-d=L4TCkU;fj3lmq$Hlk;HRoeT zbz+WP<=du1+=m_~)&ztIHaru9#dlsyDdlC(OLZyqWS-Mt-3Kks@zgXB%0Z6KsIfcm zD6O34^ND(d?^l9g5KkNvd|QI(dhUpf1|b7`9I@?hUaoREzi}l)zblk^PijdQ8EpAQ z5ho^oGAQZ(c-+FrB%GTqb5cX`8EKzUN0A`DW_35vSFDY_xL}$`)OzrJb{dypL}==$ ztRgL@N*OnCOnb&@3s-t_PS>Uv$NWE0mJvwK~8$AzqR=#qxqsrbrh4xW+FcF2#3@-NX9;#L<$KBZd$K1 zi4NmR7cYj0Jy7X})Pn9XmEJ1Atav)k0q6m((kV~^bgZbCm&ehp5F$IW!v&>Z1=3Wv zA8spJHXIM6a^}RJw8BOVS#>1wIDtCi02=6w*u6t&tUv)Pjp1wf0ER;`8xNo{;X#Pt zSX~XEf_nONu7hxMpMXhkm)2d`ct%qq?$b@$tAYPp5vGZ&7gA?U;D;h=u02Z%jcQz5 zI15@K2?j$Vu`~mXq=ZBt1_Uj5`V2ru6R@ALgnwdobm!RTulu<{2v;+#Z9&%df z`UyaGsF*2E_gT}fS-VaD_=*jC!^=k`l|;K#zxt9jmUx+1s8?;Z%Vh_0{CAx*f%=QS z?l)YVcJG^W@Yg|*X43_@T6#DW{o(~qkvyESlo}5{_ge%c2UTDW7#ELwZMJN|FL*}o z9ksT*#nEC1M+78TZue7!chX?U(a)E{PL#C&LdR!mRLHrSbx^~)5z0t50sg8gh7N&e zF|l8xa-R%sEYN_Yl0*okF5I4n&1(B4R`7DxOa)3jianlHQyWfd1{diB-Ty}NtD%8r z{?8=o#?k6FU$Yjd^=^V@rGN%w zuIW;L?%8@EwcNq7tlDa`btPB_e|=}6 zDh1U^<$uykChCRk^1g}T3=io|STv{CZug+}ThDZ{QkB3ai^okULzRHt$&oNHD2fRI ziWGz_wPr{u^l_o&URzOhVSQp6TIdw^6IrYgl$Bv(WVI{^Ac4IQpoH!ex=LjjO^ReG zbk=^wpu*Pn8;qs1_afGY7u9E#RSXyWQ4W4i(l+F~V3qc#^Mm(Q8UAj`FDG7E`P?LFL?HySv6s*n1k(CMy6kLd7C zwnn)t0uRUHFFWR<7L22QCKgb@!so8BViB7^s`rQD7lc2y_J?NI&5F?{9k*zLRq1+S z@1+n=IsYyeWF_+yzOXy04;SQ%jsGrt-w&Ur4CO@E-aVsHoa~Y(-<^HOTqU2=0+xod z1PN6hm&|KA#@CEW&gk%&gyit&fsT5)3QvGA%)9EPe^aDc4+g-tvD-!)sA7x_y^yj& z?zH)=_&SR2T{(e+1h1=RntQLFc?^WXX@}Fvc|T>v=Nr!?FzX*iB@@Ie-C7499HD)7 z8=djukt#TtEO)Ymh`=$(k`YTDmlq>hfq*73FT1^PtyV(ohuyj$R`n8Bu9+kSY_D8c zkNgrgi|;0H$)&V%!+5D2{;tTOXgC9#n)>_>0|!Pmmnp$YC2hZRaK$lnNiLmg=_k1Vh$^5A8eej~mg}PxLZvf0eQ#{^T(6z8Lb+W)i2FF?sy@E%X6U--%iBm|O5@ zQO|}r2(Ak*$gs@9;nT&eXM$=hu<`nQ`)YV8d)fmA&62>dU5>j7N@fS{(Tj)gxKTaS zUW<|MVV#=ui_FB9G3sEhRIyV@Qq;z1?l(jm)rhC+_b|#z{b{^)4!NkA(*tb(IAPr~ zUH@K}lXOTR13@u8C=Ii~&x^o;3TcWAQ}ju`)xb+)w1<_YHHG-xd8ukm6=~o&E^~YpV~3DFj-fkAR2uUni(~|7cZTaEWCOJdY#*G#6RfVPwua*Ufaoe zFFz2%CCE+olbOT&bI44p6sP!%SQO_yJ8Iw3H+=T1y)2kN?C}*QIyhkHIy~FLeW^UP z&^AELGHhsWmd;#qH)ldLgITG>&xyrGB>mWheV&ukMqb}pw3k|MXTUpCO_W$?K&l(3GR_4Y?``l5DQZRYyz&8n4|1?6i~Oyz3?O zZ)XI!?so4xLn}DXrGBI5_2R>T7Q9n%%n(Q;{(JZmp+aOV;;kVDH-Q;koTh`nnkvg% znxbJM*E#1tkEo?sCG^5J(d5Dxh^9alLW3>+Ab@3|)wSlo{i^&w+5n_MY+!!USm6x< z42VlmD+;(DL^>*u#N#2IguC^Jgbm)^U2k3rP&~$#E*G;^CfX`C9WXr`GVHVNDWMYo zm2$`Nph!^^Kc00a+?Y(=r3kqbj4gVHi8?33a<2KlNS!3}(8~4$kygcamh#_)|AT^m zPwyS5z#op(D>-5L#Mp(-#qSUqyL#RviwMY%-4ebL-~K==)aIy zQJ5rt8za6iD#jrpqFGTKUUu%@D02YN_w`OUeMfx1`u_e%vC*P#Wyy>o!Vsi^-GPY- zpoRYvO_M;}ijl-yM~oQyo|mzsCzn}OISincrOnH5Z+@K~E(t78xqL7(f8Zq>JCh|!wnd2Lc_dj$~CDb=D5h{(= zD|*Wp09~uO7~aSY>v!^Uv03dl3mtN?T3THd@O%b?t`W8YGyuaNyt!%zoRBwrPp@|w zH93BHuO3(vIFZUpvY1TTG=8=Z_${Q#yd~q^fu46q>(wG{N?gk4H;Wgg6Dhosc+`>v zk$kyoB>+|dO58W0HN?DaNRr5E6^EXeOSoZ^X{^Unox@z=I0^mFZus*hPJkU3Il0M2 zhX4yDNwGNG9{x&=*4h;2!-Z+Veg7`$4@BR$-|z<` zcc*JqUd{9$R?DTflVfH~y1~W(cY1NPT5Lc0kilfSzJG(h3p`>!mJ}@u7GFeSn63Rb z=Ly(CcmO9f-e)G|5a)uB+hnN$a_Bqj+18loq=kO!Y0{c1q857){r2SO7iYkAUVcuS zyIxp;jCDWp07!ZaCQ`Ye=utBS{hqMk`3>fK$}z`^Tojb6l(=hR^}4)XgrM{d$7Yf# zm7%onFJ|jZ7yNz|x%j@GLh?@HvH@rAChenbyp&>(0v`8FdJ3$hv6SZ8TKDH|4wbF6 zr*NAWR?5gtRL{G8e%fXD&P{1vwbZcD?FeWyLM%|1oe{jwP#asQ% z2R1%SaA=1XhX1GXNb(6)N~Jg~+}DGSje}!UcO+lmV|=Ek^h=FlQ%f_PNG%m>y1Rqh z%pLhvi@c_~RBb23hpI@Ko2cfXOLz2biKRO^zrz; zpv15#^^_qG7rwi@Pc~ji(4j#{=W|bc84rNe;zKV|0*6~ry$w*iEb^c0p;ye=Ix z-$TQ9r_wrg#wDnyb-=*KQw9E$KTjDd6xec(SV_3!&e^EGi zL-e#cT=w{~UsSJ)&%k~)P}8cjrTdY|W0tmh?7@3acz1ON{uP7}0-4KqAFb=L_W&b; z#-1t@@A~p6a$4}r<{k9A=tstsoX=x==qDtCZGha)Kq2w?-iqA+`Pk1&X_JDWTijii zWk-VLtP1_2>o2;wv1D=M<89as0kkGN01%1Y0}vMbt!tB%)gCw?I$_s*N0h5p6gpi3 zMxjJt{sgG(#zHAN0xZVyVHrFM_>)$LCHm5FQ3X*e1hv-Bp=b;LJ^&~6B#bp#(EkO( zAMwhks*6Zf_K!qdbd0gtd^s#WE6MUFOj@k57@}RPTmjHO7ioshd z^p%fO&<;qR)ceUuqyA*nV{`Ccj;X`qYjda0s{Zm58D~;10bqU_>`ny9IOx`M9leOt zUI=naH_XCX_$FlY4cK;$#^aWDX5$F%rCT)sg%fapMGz!aM^xXBcv6nQobr3DphC>0#80a zlg&#Nr?AFrUG%92k+k3)tvd2q2k7wn?;&72NC=HtJPH|sX)`omS`ga4E1>#UMW`q{ zl^DDkSWFnAL)=jm2G)H4k@vxx-H#+i)_W5O!ekmvl#Stza54HJHI7s=>+i}#2;6>8 zL*ftk6W>Qnf*|!i{CPNN`(q&0=qvq!48zn7*o4FKVx?`4Z>pV|-+~Z>_kdsF-pO&5hzxar;w16lIu@0ivlNI-MFn@RK2&`D0M2|7`s|UXmr>qfzI=One7+g`2a0eDnqPVx zX1YRL%E`kqRgCtYZL~wMwd+kn01e#DDx`wqfmNs7%$CP?w#zcr(mpONvDYN;K_oI@T+vPmMPY8r=rv~XwHCbsu z%uyNxr4@F6%rdA!l?Fpw&WIl$Du*zr<&+0TGXxAOx1LNpsTm9f3HgKk9W!O7fA@o+ z=fXs3F{F(K!!ZfGvcE6)_`yS*Sz*KLve0tSk$Os71Y)-v-Bk38HD0+}C|(yM-i6Zt zovcx)ArhiK87As`t(rY;S02>6RQ6)`LUI$%b3xmSoo1N#AUd22`a(H2Jj}qZXGJ$* zs^g)N1E!+TpZD^U@T)#+RckY2c8NUVl421Onmo(mt)2HJ;a6~4n_+6O7W>_@?SZA( zWA&?s>hro*sK>u<8jE;d$%bD01tIsDz$W~3SnawZe+i^xCazGFDAMkdgJolD041lc ze+JA(R8VJ1Z>~9zm+CgZnDxzoxB`8cd#i2;nA$g^4XKSd?m=5{l3>uU7xp2n9?UxP z70yAjwO{NBaX8wlrpA7u1;xr9&%~MwPPhT(2JKd{_<)JXNh?DQ_vcrRs9yW9h7R;b z!-{aQ%DzFky@Mf6D>_+W2v&Y@z8ETs~VeFRJo!Pq#-mpRuNM+YPLLi|;HYcohY9CKYrx zRYlJ$(PCvN8_GNCeF2Zvqf!eB9uElUe*+VF1;2IS8MLs+y_QI_!;U{7_DHw>>B}=D zO$}Q@1mWE=p{vW*-Subt1bz~$s4$r9Xc%H2x{IrOv8BJ_^+FHs?O6ef2<=8e6f~uD zfB{Bm!k-v~iKY;B!6ln%%ojEgmv6BLLBw<1pDLGoWP>JH`Z`gR7HP4bb zx*qW!(o4%fjRJB}-VCIIu400hv}?4gtwIk-RWX@d(-&~?huGC-aZ@>#az#p?c+la@ z>Bslr1ZcTtzG(xq+KG5w>HuM^^=qvK;^`j?^^bG8k31tYNrcn1eoA=8Ek8XjBYL#z zuM)J<4H8W(@`u)|9i+p;CMx#7jj*KTg!xnVPDejD%e8c93gkarV%vqvw1!pn?G$60 zN;O9@siX~7)suUb^G(A8OCZJO5Y z3PF$xm0^$q1`ewJt}?)`>-)4%XoHpoXeryc8M!Qsv=r_dfNap~<(;1Zl#7mA@P z_oU-_!@1L5T5rPkIt7$KPDk~&&y?1_hh64{25PTLpvljNA%AoYFLb{7fjN}lYY+{wm2^|${~Zbf zf-I%)ZHOUSIWW)RxdXEw%DG>Hc_{~Sxt`jn_lND;Pqj9YG@BEwkkHWnjh`1Yqm>%0 zj&Cc@hKs316@TJ1;WbUItejrX$&Kr3RcnvaBE^-5kb=2UMvnlZCUi+)dnVw%Mrl=i zc1T0^>+PAr;F9tJ333FyXRu+YpVZdQ%<1rvJB}^SpYyFYIy##jdv(%UgN^ulq!3ro zCyyCUu~f_rH@TzCDFyjx)#PTZP5+mvX|Ytg1QwfSZ+0lTQ|*|3|7L+&wbym+;Dc_C z{`zXY=euXipS}VO#c&tlA!MbDysfRB1Eb;z_?J22DjPnW(U?xjeFZ|q_ZH(j(;0KA z82njcjZ3Kwi4~NKEUTUbolcK-g}aE9nvWRs`B~=VlfFCZlYrmUj0lKwz$70T^PS-mgkdUN%>^ANrMIwJk zYaPabmdKSW;edVf6yq`tU*QyMQ)|5H_}hAMiz~1BA{B1r>cfsBss&MGkit7aU;cN7 zxG{ePM4GU~p@zcFp?`rYyCcj}T&{3yQ*?yyR?#m?OT)fv*Wf#zF)n;OjRg{|730RE zfznOFeGiJh{k04FN(i5zRh=DzU_%-!YsSP`Dv;zT8>C?T6Bw<*GKBuTz)pU?+2bl^ z2MBtJ_Z8!Kcz*#h-5>2$fW~Yj0aO(zyeUc;;f7dNBKf*swlkX5|hUoUcNP zqEJQMw6EX|`RcUNzQM=)UUY!_UVN+W7Wsqsi)VR%JPVX{GwhwTe$yTtg68Br{=66g z!n$xD>9^t4^x@?}O_%43wSywH{R)r2R;(RiSqU7c;p2(dW!@li>3o2hkmcfDH zOiv03U-F)OBoq;l0;3O9^d=1(zt2*~N`|cB3h04-yMh6SFI;7d0=V}V)>Z~qWzJcY z5E^3EWNX2rD42MTtU~$*Mp`@J8gkEEgT}Rn>|!D$y(lBelsoZRRw1`1Ja$K#J0;<; zP=Qc`e+vL)a^Yg=93W!f>V!bPAY~K7Y-{wPV@6^*pa{ds5)?`&qJ+VNN!&T(%4QmB zgHULQknEB8`;cilpH9#1Do+jEX2Tky=Yjtg>yAq$$GuaPhEpO3bN5B*h8ZWzE`|P* z_Tq@{l5P!o$ zAG*nswfUHH%!x>x_bDoKc}Zld;VE_u1)x(Ri3iGWy`cOo-3DYX(tirgA(k2jvMVt7 zzorwA>bw8d023+yk^+QC&m{h5O?88?Q9_AFmB>-^s$n46lzd;^t1q2lPk<(B6fi$P zMz*a-O7_nQKm`IYAb9TY3J+hQb4mV%s{aMU>!;GQwuLWX^#Jtl;Xt$3xsbWmMv8)i zhZ{cFogQQ3n}iUOa@vn3NVg^FBy|7c;jR0jmf%gn?k^?;5_*@1ZC#TEx%a ztgeLaZX(@O2IdejA{gY-Un`UkF)vMDtAadeEjoozM` zqy#JDL|E*VS_O{p9c==BPa&QFM6<8FEKYK=KeT^QjmBTBU~!&s&TOj`6`eZO(Bi1l z>yQGyAnsbBw>j=C2T4Dep!35E)dt->i|gaZ*GFelj$|<-3=yC zTbQp@<&TA(el}VV33zmw90+4(eWOhb&Hw~BHHgP5qA=vf_r%H4Y#eY-R+%yH`i98tkW7l?590)cjw!7qr-kKihy-1YI@hR+R%u zz5Ct%8&F&g>L1CPE0S-35{Ex{c;5n!h@+9`pO^n|D@*9KdKZ{B!Ts&NYqhDVg-!ZD zwXO(>FHE6jhGANQxRpv3v+MDz#Z59cop!FtkDmx)VlS9<34Wu;ll{Y!2#D}G{6~7T z(?+Rn`3jjr_$LI zBJ04GYzlZ5R$FYn50^A1-hd`bKys77=Eb>&`A^Y8t4Sj$Mcta-4C?)OJ2*7-Qzg7l zF0UZa2hd0WBt+CHn}0|1=VR^rAG@`m4;MkpKqWMaV4lsZc|uOWY3Npn$QwhFqWz3( zrb1RLPR*50D_IU`(cyR8UfbF+(?ERte`q&9U`@w4=scwWP{x3Ekb$EcHFZr|HpX~U z`0H7pp2N5qW^G2jc9Yo&2TUDVy`RUubwiXmyAdv08k6(f<7=wZt92Kpu{CvoUJ^FH2kQR)Y9%GY|A zxn~jF#9oKtSltl?8sD2Kc-^}gn{3<6Wh+jnb^j}Hol&F@B9CKYxT-n zdGhp0cc1E0b$0FACA)@mkXfFw11RVL{0VsQjTEaK>@~aRCun_1xPvjoF--t@d%6a? zOnp(8!;W4nUnLK*1j>sMT}RAGE5gKev#Gkg-(qJ($es3| zt2`UaYp#*?_{Gp2%8Wn`>2-vq*xWrdG~Dk-_uYs%C%@Nsr|WQ;9a?c*T#j--5Zzpq zYt2&|#xJplum5FS!Jn6>7XilJrvy&tmKMHQmmsMvRD25f^&j?Q-r;! zWz0}^)Xuvk0rjyWd^^;S@8{J%BcC>)o1`*!L=|8(_N3h@!3T1K;wppR>A>-IM4w}TUo>6!F-!R@DtW}ZDoP7r!|NTD7WRDIT& zn|tse9E_{ldaDm6_6eXWER{w%AK36DBqRWE8e3oMY&^h%J?pOuCHOm8TUBKXF3RWm zoBAs5L*CD}ad3exZAok+r0-~&GJE2bsw{)7ai8of@WTMTpi0pc7+B!WMXB+UP(TOq{qf$?=U~E><3& zt2T|iS9!mT;jIn2Z;TgD(o*WQUcIL!1=!>_0J+uO9YB|!D-t9lNFj;%y&}f^dx&MS z7E3-b>%)D$oNfEhoPa`&24d`8NaJG|6O?J#pF{N?E$OkK0#FuQHAtqT>4cMp-oLKY zC`+f13}ImPnPId65NG*{C2i@;>#qJiHE!?eZ<746{w_N;*1gN=A;R-T}$(#0$TqBV9)&mC)yPv0Yxbvdpq;`Gq zeaj^3o@?R0YnJY(bD}uXJ%c3HRE<5%Bo84RdysnrTSVQ3U?hMJ4New$xx6eERsV$& zME|AsBdYt&>-#Wa$+<3Xo5LXf=d3Gj35M0(rq_*mqZY5b@tlL0lS}PBu#E_Hxic<5 zXFT>j>;>hogT$BTu}8OPCbYRji*H6dHo}!#;-I${vt*ZC+7 zs(#ufZ8@57XO7{~rZ&bdW7=*)NUQjI(*7>}DwjeW^>u7C!-Po=QBs2l!q-ptsNhRR zlPK=>e;kChy%CA!TMrsWRPR2y>~{RSO!di>G0eZ)IU-+x+-n~TpxFOMt{65u2Ne28 za$=LIvL_jL|J_**w)%0d8Bg`1ANpp1qyAR^>3p@GnTqsgw^G8e*;1l_-hADgrQ1*cQXS>Dzw^!zYYLO3r;$S^_Jbrw>u*N_Ii*SRf0AcP$ ziO-30ouS(W%w^LBzUa6CQC75$si}t*_`8P@&v)A34HrvUIB2jZyK!!bUc&=q@=zut z6(ipy9DLdbPP$C)6R$@YXM>bepf?td@KE2lv3?Ca1Z7-6CryLY(URYSkth2qCzwR1 z(D?EeHpV4$n#SpAlUYDM&~rjdo1r58DUqBa%rQ48lG3z@VC7KXv_Ul#>aMRznRbct zB*4{IK!8J1b327=v^WVF+v?XLWmmt-sc)|#=wq4u;sNTfe}WHmy6uOLIaZrWq8Sd{ zKk4mfG=lhO(k?$s=dYw!V!>p2l0weO=d4m*QOY}L|_oz~X z9r?ZME$8>n0#HW3)NLj{K#n{5XZ%uq%3P4w_ffTU9pU%s~6?2{jJ}GZ}IkxvR`9FWq?ToD*=(KQ}f=KQ$mQ#?WIxg zVv}V2Okx$#RP5)Lyu66?cbcl8iIU(HTSC~C=JFs!>qrwVv8F66a(E7%xw(U3ZWa;J zQBncYi8>6$+f_pRV>{d#t*MIzErqX`GcSlhi9+P0UO7rck&t*1O+bI;h!tsP4u`aBdhAwg@4Bws@EZjM*`j9YxtRTuKR`-eBzqPJnU z1&hx!Q!En3?_T?KG#OIGn)OiHT3Qh`$Y-CrJ@QCvBWza8R~wkvB@a&(GvMFrv*skSqJ57WQ6B~H?l$5C~^!dKuc}3nWu9n z1Vkoc{3W_Ol#Pb;)&wYb^j26pcDYE!1jLBNaG>s&%D?5E=4R&RcM0mHhAn>y()NWZ>n^%G%&@@9*Q zWd;(Szf=^iLj@z9UF**n*Kbnwv+OzBM#V-CUe-+TUWM$R%H==7B->(X=GPu$dp@r* zxwi9Z3k82XpTR)M4!|d0-S?*Rlw`JlCh;xjCl6tYdIle~Foe73K8Z^-U^{xrV@S#n z`{j4xVz$(qzzz^I7^xvHO^3BNN<))Rp^`X_YaQOc3mm-nmvGi&Sa<-GMa@QEZdZvA z6V!G(=4mkSAk^M(wcek69rd}xl?qDhG0Yp z%)%PTX?`%m9Z(YVWBBl;w zDdBCoJA`G}Ko}o_%rFSj+Uofz;ySnlNY1fUYIho~nwB8j4t0Tgzs?@eqDM_2UuXf9 zmMGQ-_6L_(!7OdBT&4tu*z0y%)r(TQmyylWkN}2^y6gUp3pErJ0`Axso)dzlKe7? zD2-)sEF8%4qF!QZV$I;ve`8w_`vywx+NagDGBGsd2^1E8AYMexW+kjdKOg;|fXCnF6CU|;H{up zqJ9{_U-_bxk^s~*92zi1R6$gd_pX3$7E*NE!m=+Fw{m*N)JxMQuc$rfAw%wMJJo?&XkcY%px`W`p(OV+J^T?K$)fJ@fbgIxZb*Ng z@|O-)3nAjKB>w*>1Iiin-mfHFLp<4sBjOA8Zo9GrVwNH@OzidvGPJ;ukdiz)waFAr zz-puq^LZ-`)b%JPc^4a>OA4$Wf{qcm^UulXMVm9C%SLD%emMpu)PVjgE^- z5`T>Pc+E@9$cZmTY^EKhf(!+k%K+vcc}cq+(dSfDO)uz0#PAG;*&`?#M5?bMkIj1o zrK7F%mp2I|v^DW^F>P#Rac)k>6fdQegp1m96I24jVkVyqO5*MjlTU^KLs9k&4qD*Z z7EbkE%kKPF%U3K=z+PgYUR{p~=MnK&o%!de#M96Kim<2bE8w3ppFUpT=WjBGiY7O_ ziS?A`&;ug7R}a&rB7cp_e})(Z7wZ!)xsz*MEecJ&b`7#yA2?COj@IFcqbwAazG4 zM203N2466>wbOS`^o&hSBN4RS%X&Xw*Zb)U z?Q`?DQ@T?9lt_y4?SWYg81*E%>|6JKVWjC)!D*{48(|L1b4ld;hb)K?EimMKpTW$j zAr*7v))ZhSaf}cN!ag8aTyLPP(STU9T*$cClmI}>yd)@I5c*O)jK7%guOrALWtbf7 zi**6kM-K=L=aTl<746j(3A!S~EJPcSm_ky>|G!N}blBxf!;1bQPw;q8Nb+HVs36-^E9=2_1@tlX=3Uq#If6Rk`WjchV>HYmAy`#XWSUoT;)1S!{n#NY(*+)(nOyaS}bLEMy%W zsC$vy8AnV3dB5)$$0M@$9!GSE&BFe7Xm+q?#mE|R@{-Ko-%DedZzQ)`$^GNl`L-U@ z`4{WAwj}-kUU;N{0J0Qn!X%7AKw3G>dOaL$e2jZ&4it;Di zBLK{>u)Ygw!1eDfQ-J>c4nwxlZYl69aO9u`>`;pW+O(Z$f82bf;=(2p1^$ru$9?5H zeH=;4A#wQpSpW<;Z}m>!&! z7Y42lcvKl>b=YXc0fuNjVFW}^hU|UE{|+>T8n6?|ll3RM|2d}s)~OWuRFvEwnVaug z^yg&cf8Qbadr|lpV=UP}+Dj%ulLTg9w)$h^c=Z1LyGfXULyF-t$zaC6H~M#41T@J6 ziZm8-I1i=&UhlsLr~5bS_R!Fm>m&}Km1eu=I(uV+_uU`u zPZ=3RKF>i~U9r+$+^ZMeo_5=b^Uz4yD1+ZQY#1Fi_yGY;Jzs4MXLb#7okndyw(V@K zHbvURY-Auhdc5Y+N;=Ihyxm8=N~5fEJTCuHn9k0K*X6f)^~!l`YwIC>@GHBYh3SE? z&BXobLYMULLVOCPHyQbTb@yUWUQ?gvcv#(!$KMKW&A3BDLlzc)#A6|WhKp=Bc?%B5 zwN~t+|2+r!2>*y$&Dv8U_SC5pP`a`*3()tC#x={+H75<&#q}!BxSwZD7hE`ms72$8 z*-eZbK-HT+mRk6_R)EH!G){1d5;9Ub?~{jhh0W@88W8H08yI-%FxvXn z=VvGLcL5}pWA{G!WxFMlHY;sz3+>9{aYrBLVVkBVDQ)$0;}hd6%{HzNwjEjRxNsSI zS;2A5hgV65vDpf|$)2EmE|!bG7qp^G5g9_hX|@@H!$Ii5t@<53dfCaHPyY;IJZW1f zT`5!)NMLh&|21mx_~foysqubjhb8(=^(_Fj|1c$dz5SAgPeYpgg?A6{N&;^H#xKUn`Aw_M>B z_WkGlw9re_gxzLWyXRXIM{!q!#R=hD_SLg{IF!l{R$mc0xydZOcVttc=I`@n9}OUB zJ8uSN+NcM@8i)@BJoJv%G-?8w;<3<@8I;!-gPR}EFCJ87KpR=1^9HNg@x@hiNO~Ql z&GwI@JG^EQ1EzAaVL7*xHLUlO%L+vrH9M>vtMPolAM}3JD|1y&c=E{2>FG;V-1q%3 z)YLm1b2gc3vNN>LTz*W>K;KJbB0i=NPtQ5)S!R^Ts&B1pV|l0*3${U|x2391&lL=s zy@R#}SKIB?V3V6P9KB~W3KBoO`k#GeGv~rO+OdCt%(iv5V#0Sty5wDu9?8$?g=sa^Wl?BEzV4T zC;8k|?0Oi4A%nbIizkQeGP=(jIZwni6Qf`@G7_&J2@va**F2HvrNbJuTViQ+3-an6 zF&>paJ_eJ3dkHlU4h$H4CHP!iWfKx^H4`slHWikRlc|68ZD8KqV&ZuEr$>}&OltK8 zEgO297}A`!@36U)R5^w`ij1AC-*Qo+)5t!})l~%I$y1Z%48#!25xb0F^yp$cJ1Z$v z=(gaakWW6BOv&XcyXBGJq1cZVaXe1i*ZAjO84OFgWiWG{frsh`xxHq5EV5uG|J%uG3 zZH~d;N}Or6rVhP7XufcmFcms9d(4KSL=h8by)Q4v&3&E2fy=FafsLqjaQms-jwGT% zad`z@oz`3%(929hQYN|U?+M!Vav<(ISySkLg0$jTzqNnJ$9k<5vlq+p54wEkC z07AVVTv#@~R}*W&1E1FdJ-t4vepPo}?_^&1P)U`G-5oks9`=9PTilBvV}k!9v+1_= zILfANZv`|>{^7@i-i8<|Afhkh;h{3JA5L^gkD=U-ga5p;$5i#5Bh-FiU7eyE#^r9X z*(oVWSrJ=}H(lCFr5dc8nw)#L(SebglmsgGRi{yEe}+uAr_%5HONsgN)S}f&GE+a) z0~D7cn&U=N1JtH@_T?w@Nb> zLb5ALqIhR>Sm5|$n)W@x*wKzhPIFvJ??9tsMo3aEffOay2f5=g&Smqul@TLD#o+U~ z;$rb_Q(l-Dt>^ERDj8RiRX@uDjZ&7C$Xm(N&C zR=}%2DYD3BrIK=%1*a6D-=QxRJTcWM##X3Pp)MFba+j`6*!XSGIHc$9E}*&m-o2TNoaND|{V`8P&z$9l}Y2Hvx+wU2EStxID<~?MimO`%-Eu zon7~UlXHm#G4$rpH^LkcsU@eo8vELyBRM1v(|wS-kY9zC9M6xxR=Q*%yfVy3tDzt>@0{t#H`g&s=5O2u z96htdxzcGoG4E2^nUA=kA!QEzZPKY#L3p?ar3J%51H@JbWuBu4ATx@hz zTVA>NJl@$2=NTiBm6Kn^jSz2+|KtFG&-!OktzDkIQmSuI= zvRQ>I78R9@>1(H-5SztB|9Iu~54Y3AHmYf^2$!a$eia+w@ZHn-e0ruDs`S`?#m)6x ze60pL3qv>T%k=w@-cnR-6U1IWm`@mqadaVAi0%C_z(GUzk7fn=sfR+3o$L=7nm_U% zI^hK2`kHHPMn5VmWI#}Tu^6rZsz95`!De zT&GI(e5pz;*hNbf<Z;`)#n6K%TW%$Q0qhL%ow-2mEYG417LHPdI8DP`{Xc zbbze*95ld6_&uFfGmnb1f;BD{tD@J)%BWPW1RILk%iF|#pN`V_TCTW&Ote-aThViu z>AKATv7~7r5sIkPpjNus#n(u1YO_Bo_gII`pcAFz_?^8BsET8mTf~85)5jwJ#{m)t z1fsYb+E7dUDN!F9{heowXVGd4f~B0y;)(4>JEv4dLgONdI5%{ zjUtF%;wqp9+1(}25rv1ucgr8>22kf*h~>&N9e!ESClsn-P&i-SpVeeLD|ed6l55AY zPuG&7_k-DVWv-UdO(&`Y36CVd${+;IWUERHpEVdexVTO&@3%QteQ1fsBt|Ez)rtTs z>3Kf3`=KZj&lZdlDm+a>QdXkr&wW-55y=9O`(7-}E4&#zL@@9EKC+^1<&EE|{t+_+ zdy0z+Sxf8^$r$94CRNw$YHwa{pB{GfTRKd-Y9k!T4{qG0rGufVrfgwLPh!55+aHmA zh7^V?Jt3p9lrhh=jw(j1kwES8(uD6HlGc!PVWB<6F~ugO&=NmPz z)@w-?qj5Z)FZIe?=|S}C((2V>zLDLg;^6V|7399#>zpRU&wSZGo?@QEIl_p?FS33% zuLo6LC`TaugldC=z-C*cVPo4iRJ_jWkR3+*7tvNUyW2TmaFuZlLtKg3#Fn)BRzrwq z(9b@{Um;QI5fZxA`@FW}Tc4_9#N)-k7C6#na+L4uf**QJA>Jg=_KR(|)(Z&C|6;ozZTZM2xV6j+Cb^1L#0#(+)frQo!<{YWh zQPrm15rUX37N_~tnuZu{WM-yIIMZ}#L`-CUk0@d&%juB8XiUuAu{Ib3{{8v>IJ$AIj4buMHZE9_j~$$Eg0gccS{R^*15-t3`^ED;$CPe0Dtdcuj085eTL zc2n3Ni8gR49NJ(~hnp9*5f{3^rmkYqW_U+B7>lG2me5S0uaZfwHc^$Mzb{sBw=mlaz^g@&NMf zPSLb^y6bH?IFdP~s76Y%5OmJbgOa>-p(G(M2fsw(zRE zZtqS#H1sIBMKM@Hq5J8Qzl6f!eQwxYLF6_L(D6bxXdYuC(_89%fN`bLsgca#w zhSOK^qt%6+&85xa&$FpxwD)~nMt+nAq4~tsU=u4I;ZG7=x-0tycc!K>q>^w-$7Ex{6je@*W>A6 zcu;3HRBsz;!G8l3xf6^$4wDsnj?uX{%GqjOyY`+?#W$V#Y{kV%bAO2!dAPrB3Tc zh@Q~!NVxw67pBPq%nC4kI=*%ClpEpBaM(iY#m-fsrqqY%-rl%6Rq4WJ7@%?p_2s9y zNju?!foaR^e#1&{S*YC9{T?=2o8XTGrV`1ub&2)Y591I9m~Hu_GGBQ!Vx5*Xg;G7j zf4?3Nv3D;8f3<|IdioYFTA9`V$#W?O*9=sc3d_5T_J0-)pe0lB0+KYMoY^6L+%D|2 z2Mg=@6Zp?)iM0+s46G@sIf{n1NBJ>WjVO@;m|jZ