Repository: bridgecrewio/checkov

Issue:
BC_AWS_PUBLIC_1 does not take Conditions into account
**Describe the bug**
BC_AWS_PUBLIC_1 seems to only look for the principal in a ECR Resource Policy. If you want to control access to a repo based on the pricipals AWS Organization ID, you have to do this using a condition instead of a Principal. It seems like checkov does not take this into account.

Example:

``` yaml
  Repository:
    Type: AWS::ECR::Repository
    Properties:
      RepositoryName: !Ref RepoName
      RepositoryPolicyText:
        Version: "2012-10-17"
        Statement:
          - Sid: OrgRead
            Effect: Allow
            Principal: "*"
            Action:
              - ecr:GetAuthorizationToken
              - ecr:BatchCheckLayerAvailability
              - ecr:GetDownloadUrlForLayer
              - ecr:GetRepositoryPolicy
              - ecr:DescribeRepositories
              - ecr:ListImages
              - ecr:DescribeImages
              - ecr:BatchGetImage
              - ecr:DescribeImageScanFindings
            Condition:
              ForAllValues:StringEquals:
                aws:PrincipalOrgID: "o-12345678"
```  

**To Reproduce**
Create the above mentioned resource in cloudformation and scan it with checkov

**Expected behavior**
I expect checkov to look for the usage of a PrincipalOrgID or similar global condition keys and not fail the check when they are used to make the repository non public.

**Desktop (please complete the following information):**
 - OS: macOS 11.5.2
 - Checkov Version 2.0.390



Discussion:

Resolving patch:
diff --git a/checkov/cloudformation/checks/resource/aws/ECRPolicy.py b/checkov/cloudformation/checks/resource/aws/ECRPolicy.py
--- a/checkov/cloudformation/checks/resource/aws/ECRPolicy.py
+++ b/checkov/cloudformation/checks/resource/aws/ECRPolicy.py
@@ -31,9 +31,22 @@ def scan_resource_conf(self, conf):
                     for statement_index, statement in enumerate(policy_text['Statement']):
                         if 'Principal' in statement.keys():
                             for principal_index, principal in enumerate(statement['Principal']):
-                                if principal == "*":
+                                if principal == "*" and not self.check_for_constrained_condition(statement):
                                     self.evaluated_keys = [f"Properties/RepositoryPolicyText/Statement/[{statement_index}]/Principal/[{principal_index}]"]
                                     return CheckResult.FAILED
         return CheckResult.PASSED
 
+    def check_for_constrained_condition(self, statement):
+        """
+        Checks to see if there is a constraint on a a wildcarded principal
+        :param statement: statement from aws_repository_configuration
+        :return: true if there is a constraint
+        """
+        if 'Condition' in statement.keys():
+            condition = statement['Condition']
+            if 'ForAllValues:StringEquals' in condition.keys():
+                if 'aws:PrincipalOrgID' in condition['ForAllValues:StringEquals'].keys():
+                    return True
+        return False
+
 check = ECRPolicy()
diff --git a/checkov/terraform/checks/resource/aws/ECRPolicy.py b/checkov/terraform/checks/resource/aws/ECRPolicy.py
--- a/checkov/terraform/checks/resource/aws/ECRPolicy.py
+++ b/checkov/terraform/checks/resource/aws/ECRPolicy.py
@@ -27,7 +27,7 @@ def scan_resource_conf(self, conf):
                 statement = policy['Statement'][0]
                 if statement['Principal'] and type(statement['Principal']) is str:
                     principal = statement['Principal']
-                    if principal == "*":
+                    if principal == "*"  and not self.check_for_constrained_condition(statement):
                         self.evaluated_keys = ["policy/Statement/Principal"]
                         return CheckResult.FAILED
         return CheckResult.PASSED
@@ -35,5 +35,17 @@ def scan_resource_conf(self, conf):
     def get_evaluated_keys(self) -> List[str]:
         return ['policy']
 
+    def check_for_constrained_condition(self, statement):
+        """
+        Checks to see if there is a constraint on a a wildcarded principal
+        :param statement: statement from aws_repository_configuration
+        :return: True if there is a constraint
+        """
+        if 'Condition' in statement and isinstance(statement['Condition'], dict):
+            condition = statement['Condition']
+            if 'ForAllValues:StringEquals' in condition and isinstance(condition['ForAllValues:StringEquals'], dict):
+                if 'aws:PrincipalOrgID' in condition['ForAllValues:StringEquals']:
+                    return True
+        return False
 
 check = ECRPolicy()


Test patch:
diff --git a/tests/cloudformation/checks/resource/aws/example_ECRPolicy/ECRPolicy-PASSED-2.yaml b/tests/cloudformation/checks/resource/aws/example_ECRPolicy/ECRPolicy-PASSED-2.yaml
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/checks/resource/aws/example_ECRPolicy/ECRPolicy-PASSED-2.yaml
@@ -0,0 +1,24 @@
+AWSTemplateFormatVersion: "2010-09-09"
+Resources: 
+  MyRepository: 
+    Type: AWS::ECR::Repository
+    Properties: 
+      RepositoryName: "test-repository"
+      RepositoryPolicyText: 
+        Version: "2012-10-17"
+        Statement: 
+          - 
+            Sid: AllowPushPull
+            Effect: Allow
+            Principal: "*"
+            Action: 
+              - "ecr:GetDownloadUrlForLayer"
+              - "ecr:BatchGetImage"
+              - "ecr:BatchCheckLayerAvailability"
+              - "ecr:PutImage"
+              - "ecr:InitiateLayerUpload"
+              - "ecr:UploadLayerPart"
+              - "ecr:CompleteLayerUpload"
+            Condition:
+              ForAllValues:StringEquals:
+                aws:PrincipalOrgID: "o-12345678"
\ No newline at end of file
diff --git a/tests/cloudformation/checks/resource/aws/test_ECRPolicy.py b/tests/cloudformation/checks/resource/aws/test_ECRPolicy.py
--- a/tests/cloudformation/checks/resource/aws/test_ECRPolicy.py
+++ b/tests/cloudformation/checks/resource/aws/test_ECRPolicy.py
@@ -16,7 +16,7 @@ def test_summary(self):
         report = runner.run(root_folder=test_files_dir,runner_filter=RunnerFilter(checks=[check.id]))
         summary = report.get_summary()
 
-        self.assertEqual(summary['passed'], 2)
+        self.assertEqual(summary['passed'], 3)
         self.assertEqual(summary['failed'], 1)
         self.assertEqual(summary['skipped'], 0)
         self.assertEqual(summary['parsing_errors'], 0)
diff --git a/tests/terraform/checks/resource/aws/example_ECRPolicy/main.tf b/tests/terraform/checks/resource/aws/example_ECRPolicy/main.tf
--- a/tests/terraform/checks/resource/aws/example_ECRPolicy/main.tf
+++ b/tests/terraform/checks/resource/aws/example_ECRPolicy/main.tf
@@ -82,4 +82,84 @@ resource "aws_ecr_repository" "empty" {
 resource "aws_ecr_repository_policy" "empty" {
   repository = aws_ecr_repository.empty.name
   policy     = ""
+}
+
+resource "aws_ecr_repository" "conditional_ok" {
+  name = "conditional_ok_repo"
+}
+
+resource "aws_ecr_repository_policy" "pass_conditional" {
+  repository = aws_ecr_repository.conditional_ok.name
+  policy     = <<POLICY
+{   "Version": "2008-10-17",
+    "Statement": [
+        {
+            "Sid": "new policy",
+            "Effect": "Allow",
+            "Principal": "*",
+            "Action": [
+                "ecr:GetDownloadUrlForLayer",
+                "ecr:BatchGetImage",
+                "ecr:BatchCheckLayerAvailability",                
+                "ecr:PutImage",
+                "ecr:InitiateLayerUpload",                
+                "ecr:UploadLayerPart",
+                "ecr:CompleteLayerUpload",                
+                "ecr:DescribeRepositories",                
+                "ecr:GetRepositoryPolicy",                
+                "ecr:ListImages",                
+                "ecr:DeleteRepository",
+                "ecr:BatchDeleteImage",                
+                "ecr:SetRepositoryPolicy",
+                "ecr:DeleteRepositoryPolicy"
+            ],        
+            "Condition": {
+                "ForAllValues:StringEquals": {
+                    "aws:PrincipalOrgID": "o-12345678"
+                }
+            }
+        }   
+    ]
+    }
+POLICY
+}
+
+resource "aws_ecr_repository" "conditional_bad" {
+  name = "conditional_bad_repo"
+}
+
+resource "aws_ecr_repository_policy" "fail_conditional" {
+  repository = aws_ecr_repository.conditional_bad.name
+  policy     = <<POLICY
+{   "Version": "2008-10-17",
+    "Statement": [
+        {
+            "Sid": "new policy",
+            "Effect": "Allow",
+            "Principal": "*",
+            "Action": [
+                "ecr:GetDownloadUrlForLayer",
+                "ecr:BatchGetImage",
+                "ecr:BatchCheckLayerAvailability",                
+                "ecr:PutImage",
+                "ecr:InitiateLayerUpload",                
+                "ecr:UploadLayerPart",
+                "ecr:CompleteLayerUpload",                
+                "ecr:DescribeRepositories",                
+                "ecr:GetRepositoryPolicy",                
+                "ecr:ListImages",                
+                "ecr:DeleteRepository",
+                "ecr:BatchDeleteImage",                
+                "ecr:SetRepositoryPolicy",
+                "ecr:DeleteRepositoryPolicy"
+            ],
+            "Condition": {
+                "ForAllValues:StringEquals": {
+                    "aws:username": "pull-user-1"
+                }
+            }
+        }   
+    ]
+    }
+POLICY
 }
\ No newline at end of file
diff --git a/tests/terraform/checks/resource/aws/test_ECRPolicy.py b/tests/terraform/checks/resource/aws/test_ECRPolicy.py
--- a/tests/terraform/checks/resource/aws/test_ECRPolicy.py
+++ b/tests/terraform/checks/resource/aws/test_ECRPolicy.py
@@ -20,22 +20,23 @@ def test(self):
         passing_resources = {
             "aws_ecr_repository_policy.pass",
             "aws_ecr_repository_policy.empty",
+            "aws_ecr_repository_policy.pass_conditional",
         }
         failing_resources = {
             "aws_ecr_repository_policy.fail",
+            "aws_ecr_repository_policy.fail_conditional",
         }
 
         passed_check_resources = set([c.resource for c in report.passed_checks])
         failed_check_resources = set([c.resource for c in report.failed_checks])
 
-        self.assertEqual(summary["passed"], 2)
-        self.assertEqual(summary["failed"], 1)
+        self.assertEqual(summary["passed"], 3)
+        self.assertEqual(summary["failed"], 2)
         self.assertEqual(summary["skipped"], 0)
         self.assertEqual(summary["parsing_errors"], 0)
 
         self.assertEqual(passing_resources, passed_check_resources)
         self.assertEqual(failing_resources, failed_check_resources)
 
-
 if __name__ == "__main__":
-    unittest.main()
+    unittest.main()
\ No newline at end of file