github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/rules/cloud/policies/aws/iam/no_policy_wildcards.go (about)

     1  package iam
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/khulnasoft-lab/defsec/pkg/framework"
     8  
     9  	"github.com/khulnasoft-lab/defsec/pkg/providers/aws/iam"
    10  	"github.com/khulnasoft-lab/defsec/pkg/severity"
    11  
    12  	"github.com/khulnasoft-lab/defsec/pkg/state"
    13  
    14  	"github.com/khulnasoft-lab/defsec/pkg/scan"
    15  
    16  	"github.com/khulnasoft-lab/defsec/internal/rules"
    17  
    18  	"github.com/khulnasoft-lab/defsec/pkg/providers"
    19  
    20  	"github.com/liamg/iamgo"
    21  )
    22  
    23  var CheckNoPolicyWildcards = rules.Register(
    24  	scan.Rule{
    25  		AVDID:     "AVD-AWS-0057",
    26  		Provider:  providers.AWSProvider,
    27  		Service:   "iam",
    28  		ShortCode: "no-policy-wildcards",
    29  		Frameworks: map[framework.Framework][]string{
    30  			framework.Default:     nil,
    31  			framework.CIS_AWS_1_4: {"1.16"},
    32  		},
    33  		Summary:     "IAM policy should avoid use of wildcards and instead apply the principle of least privilege",
    34  		Impact:      "Overly permissive policies may grant access to sensitive resources",
    35  		Resolution:  "Specify the exact permissions required, and to which resources they should apply instead of using wildcards.",
    36  		Explanation: `You should use the principle of least privilege when defining your IAM policies. This means you should specify each exact permission required without using wildcards, as this could cause the granting of access to certain undesired actions, resources and principals.`,
    37  		Links: []string{
    38  			"https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html",
    39  		},
    40  		Terraform: &scan.EngineMetadata{
    41  			GoodExamples:        terraformNoPolicyWildcardsGoodExamples,
    42  			BadExamples:         terraformNoPolicyWildcardsBadExamples,
    43  			Links:               terraformNoPolicyWildcardsLinks,
    44  			RemediationMarkdown: terraformNoPolicyWildcardsRemediationMarkdown,
    45  		},
    46  		CloudFormation: &scan.EngineMetadata{
    47  			GoodExamples:        cloudFormationNoPolicyWildcardsGoodExamples,
    48  			BadExamples:         cloudFormationNoPolicyWildcardsBadExamples,
    49  			Links:               cloudFormationNoPolicyWildcardsLinks,
    50  			RemediationMarkdown: cloudFormationNoPolicyWildcardsRemediationMarkdown,
    51  		},
    52  		Severity: severity.High,
    53  	},
    54  	func(s *state.State) (results scan.Results) {
    55  		for _, policy := range s.AWS.IAM.Policies {
    56  			if policy.Builtin.IsTrue() {
    57  				continue
    58  			}
    59  			results = checkPolicy(policy.Document, results)
    60  		}
    61  		for _, group := range s.AWS.IAM.Groups {
    62  			for _, policy := range group.Policies {
    63  				if policy.Builtin.IsTrue() {
    64  					continue
    65  				}
    66  				results = checkPolicy(policy.Document, results)
    67  			}
    68  		}
    69  		for _, user := range s.AWS.IAM.Users {
    70  			for _, policy := range user.Policies {
    71  				if policy.Builtin.IsTrue() {
    72  					continue
    73  				}
    74  				results = checkPolicy(policy.Document, results)
    75  			}
    76  		}
    77  		for _, role := range s.AWS.IAM.Roles {
    78  			for _, policy := range role.Policies {
    79  				if policy.Builtin.IsTrue() {
    80  					continue
    81  				}
    82  				results = checkPolicy(policy.Document, results)
    83  			}
    84  		}
    85  		return results
    86  	},
    87  )
    88  
    89  func checkPolicy(src iam.Document, results scan.Results) scan.Results {
    90  	statements, _ := src.Parsed.Statements()
    91  	for _, statement := range statements {
    92  		results = checkStatement(src, statement, results)
    93  	}
    94  	return results
    95  }
    96  
    97  // nolint
    98  func checkStatement(src iam.Document, statement iamgo.Statement, results scan.Results) scan.Results {
    99  	effect, _ := statement.Effect()
   100  	if effect != iamgo.EffectAllow {
   101  		return results
   102  	}
   103  
   104  	actions, r := statement.Actions()
   105  	for _, action := range actions {
   106  		if strings.Contains(action, "*") {
   107  			results.Add(
   108  				fmt.Sprintf(
   109  					"IAM policy document uses wildcarded action '%s'",
   110  					actions[0],
   111  				),
   112  				src.MetadataFromIamGo(statement.Range(), r),
   113  			)
   114  		} else {
   115  			results.AddPassed(src)
   116  		}
   117  	}
   118  
   119  	resources, r := statement.Resources()
   120  	for _, resource := range resources {
   121  		if strings.Contains(resource, "*") {
   122  			if allowed, action := iam.IsWildcardAllowed(actions...); !allowed {
   123  				if strings.HasSuffix(resource, "/*") && strings.HasPrefix(resource, "arn:aws:s3") {
   124  					continue
   125  				}
   126  				results.Add(
   127  					fmt.Sprintf("IAM policy document uses sensitive action '%s' on wildcarded resource '%s'", action, resources[0]),
   128  					src.MetadataFromIamGo(statement.Range(), r),
   129  				)
   130  			} else {
   131  				results.AddPassed(src)
   132  			}
   133  		} else {
   134  			results.AddPassed(src)
   135  		}
   136  	}
   137  	principals, _ := statement.Principals()
   138  	if all, r := principals.All(); all {
   139  		results.Add(
   140  			"IAM policy document uses wildcarded principal.",
   141  			src.MetadataFromIamGo(statement.Range(), r),
   142  		)
   143  	}
   144  	aws, r := principals.AWS()
   145  	for _, principal := range aws {
   146  		if strings.Contains(principal, "*") {
   147  			results.Add(
   148  				"IAM policy document uses wildcarded principal.",
   149  				src.MetadataFromIamGo(statement.Range(), r),
   150  			)
   151  		} else {
   152  			results.AddPassed(src)
   153  		}
   154  	}
   155  
   156  	return results
   157  }