github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/internal/adapters/terraform/aws/iam/policies.go (about)

     1  package iam
     2  
     3  import (
     4  	"github.com/aquasecurity/defsec/pkg/providers/aws/iam"
     5  	"github.com/aquasecurity/defsec/pkg/terraform"
     6  	defsecTypes "github.com/aquasecurity/defsec/pkg/types"
     7  	"github.com/liamg/iamgo"
     8  )
     9  
    10  func parsePolicy(policyBlock *terraform.Block, modules terraform.Modules) (iam.Policy, error) {
    11  	policy := iam.Policy{
    12  		Metadata: policyBlock.GetMetadata(),
    13  		Name:     policyBlock.GetAttribute("name").AsStringValueOrDefault("", policyBlock),
    14  		Document: iam.Document{
    15  			Metadata: defsecTypes.NewUnmanagedMetadata(),
    16  			Parsed:   iamgo.Document{},
    17  			IsOffset: false,
    18  			HasRefs:  false,
    19  		},
    20  		Builtin: defsecTypes.Bool(false, policyBlock.GetMetadata()),
    21  	}
    22  	var err error
    23  	doc, err := ParsePolicyFromAttr(policyBlock.GetAttribute("policy"), policyBlock, modules)
    24  	if err != nil {
    25  		return policy, err
    26  	}
    27  	policy.Document = *doc
    28  	return policy, nil
    29  }
    30  
    31  func adaptPolicies(modules terraform.Modules) (policies []iam.Policy) {
    32  	for _, policyBlock := range modules.GetResourcesByType("aws_iam_policy") {
    33  		policy, err := parsePolicy(policyBlock, modules)
    34  		if err != nil {
    35  			continue
    36  		}
    37  		policies = append(policies, policy)
    38  	}
    39  	return
    40  }
    41  
    42  // applyForDependentResource returns the result of
    43  // applying the function to the dependent block from the parent block and true
    44  // if the parent block was found.
    45  //
    46  //	resource "aws_s3_bucket" "this" {
    47  //	  bucket = ...
    48  //	  ...
    49  //	}
    50  //
    51  //	resource "aws_s3_bucket_logging" "this" {
    52  //	  bucket = aws_s3_bucket.this.id
    53  //	  ...
    54  //	}
    55  func applyForDependentResource[T any](
    56  	modules terraform.Modules,
    57  	refBlockID string,
    58  	refAttrName string,
    59  	dependentResourceType string,
    60  	dependentAttrName string,
    61  	fn func(resource *terraform.Block) T,
    62  ) (T, bool) {
    63  	for _, resource := range modules.GetResourcesByType(dependentResourceType) {
    64  		relatedAttr := resource.GetAttribute(dependentAttrName)
    65  		if relatedAttr.IsNil() {
    66  			continue
    67  		}
    68  
    69  		refBlock, err := modules.GetBlockById(refBlockID)
    70  		if err != nil {
    71  			continue
    72  		}
    73  
    74  		if isDependentBlock(refBlock, refAttrName, relatedAttr) {
    75  			return fn(resource), true
    76  		}
    77  	}
    78  	var res T
    79  	return res, false
    80  }
    81  
    82  func isDependentBlock(refBlock *terraform.Block, refAttrName string, relatedAttr *terraform.Attribute) bool {
    83  	refAttr := refBlock.GetAttribute(refAttrName).AsStringValueOrDefault("", refBlock).Value()
    84  	return relatedAttr.Equals(refBlock.ID()) || relatedAttr.Equals(refAttr) || relatedAttr.ReferencesBlock(refBlock)
    85  }
    86  
    87  func findPolicy(modules terraform.Modules) func(resource *terraform.Block) *iam.Policy {
    88  	return func(resource *terraform.Block) *iam.Policy {
    89  		policy, err := parsePolicy(resource, modules)
    90  		if err != nil {
    91  			return nil
    92  		}
    93  		return &policy
    94  	}
    95  }
    96  
    97  func findAttachmentPolicy(modules terraform.Modules) func(resource *terraform.Block) *iam.Policy {
    98  	return func(resource *terraform.Block) *iam.Policy {
    99  		policyAttr := resource.GetAttribute("policy_arn")
   100  		if policyAttr.IsNil() {
   101  			return nil
   102  		}
   103  		policyBlock, err := modules.GetReferencedBlock(policyAttr, resource)
   104  		if err != nil {
   105  			return nil
   106  		}
   107  		return findPolicy(modules)(policyBlock)
   108  	}
   109  }