github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/terraform/module.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  )
     7  
     8  type Module struct {
     9  	blocks     Blocks
    10  	blockMap   map[string]Blocks
    11  	rootPath   string
    12  	modulePath string
    13  	ignores    Ignores
    14  }
    15  
    16  func NewModule(rootPath string, modulePath string, blocks Blocks, ignores Ignores) *Module {
    17  
    18  	blockMap := make(map[string]Blocks)
    19  
    20  	for _, b := range blocks {
    21  		if b.NameLabel() != "" {
    22  			blockMap[b.TypeLabel()] = append(blockMap[b.TypeLabel()], b)
    23  		}
    24  	}
    25  
    26  	return &Module{
    27  		blocks:     blocks,
    28  		ignores:    ignores,
    29  		blockMap:   blockMap,
    30  		rootPath:   rootPath,
    31  		modulePath: modulePath,
    32  	}
    33  }
    34  
    35  func (c *Module) RootPath() string {
    36  	return c.rootPath
    37  }
    38  
    39  func (c *Module) Ignores() Ignores {
    40  	return c.ignores
    41  }
    42  
    43  func (c *Module) GetBlocks() Blocks {
    44  	return c.blocks
    45  }
    46  
    47  func (h *Module) GetBlocksByTypeLabel(typeLabel string) Blocks {
    48  	return h.blockMap[typeLabel]
    49  }
    50  
    51  func (c *Module) getBlocksByType(blockType string, labels ...string) Blocks {
    52  	if blockType == "module" {
    53  		return c.getModuleBlocks()
    54  	}
    55  	var results Blocks
    56  	for _, label := range labels {
    57  		for _, block := range c.blockMap[label] {
    58  			if block.Type() == blockType {
    59  				results = append(results, block)
    60  			}
    61  		}
    62  	}
    63  	return results
    64  }
    65  
    66  func (c *Module) getModuleBlocks() Blocks {
    67  	var results Blocks
    68  	for _, block := range c.blocks {
    69  		if block.Type() == "module" {
    70  			results = append(results, block)
    71  		}
    72  	}
    73  	return results
    74  }
    75  
    76  func (c *Module) GetResourcesByType(labels ...string) Blocks {
    77  	return c.getBlocksByType("resource", labels...)
    78  }
    79  
    80  func (c *Module) GetResourcesByIDs(ids ...string) Blocks {
    81  	var blocks Blocks
    82  
    83  	for _, id := range ids {
    84  		if block := c.blocks.WithID(id); block != nil {
    85  			blocks = append(blocks, block)
    86  		}
    87  	}
    88  	return blocks
    89  }
    90  
    91  func (c *Module) GetDatasByType(label string) Blocks {
    92  	return c.getBlocksByType("data", label)
    93  }
    94  
    95  func (c *Module) GetProviderBlocksByProvider(providerName string, alias string) Blocks {
    96  	var results Blocks
    97  	for _, block := range c.blocks {
    98  		if block.Type() == "provider" && len(block.Labels()) > 0 && block.TypeLabel() == providerName {
    99  			if alias != "" {
   100  				if block.HasChild("alias") && block.GetAttribute("alias").Equals(strings.ReplaceAll(alias, fmt.Sprintf("%s.", providerName), "")) {
   101  					results = append(results, block)
   102  
   103  				}
   104  			} else if block.MissingChild("alias") {
   105  				results = append(results, block)
   106  			}
   107  		}
   108  	}
   109  	return results
   110  }
   111  
   112  func (c *Module) GetReferencedBlock(referringAttr *Attribute, parentBlock *Block) (*Block, error) {
   113  	for _, ref := range referringAttr.AllReferences() {
   114  		if ref.TypeLabel() == "each" {
   115  			if forEachAttr := parentBlock.GetAttribute("for_each"); forEachAttr.IsNotNil() {
   116  				if b, err := c.GetReferencedBlock(forEachAttr, parentBlock); err == nil {
   117  					return b, nil
   118  				}
   119  			}
   120  		}
   121  		for _, block := range c.blocks {
   122  			if ref.RefersTo(block.reference) {
   123  				return block, nil
   124  			}
   125  			kref := *ref
   126  			kref.SetKey(parentBlock.reference.RawKey())
   127  			if kref.RefersTo(block.reference) {
   128  				return block, nil
   129  			}
   130  		}
   131  	}
   132  	return nil, fmt.Errorf("no referenced block found in '%s'", referringAttr.Name())
   133  }
   134  
   135  func (c *Module) GetBlockByID(id string) (*Block, error) {
   136  	found := c.blocks.WithID(id)
   137  	if found == nil {
   138  		return nil, fmt.Errorf("no block found with id '%s'", id)
   139  	}
   140  	return found, nil
   141  }
   142  
   143  func (c *Module) GetReferencingResources(originalBlock *Block, referencingLabel string, referencingAttributeName string) Blocks {
   144  	return c.GetReferencingBlocks(originalBlock, "resource", referencingLabel, referencingAttributeName)
   145  }
   146  
   147  func (c *Module) GetsModulesBySource(moduleSource string) (Blocks, error) {
   148  	var results Blocks
   149  
   150  	modules := c.getModuleBlocks()
   151  	for _, module := range modules {
   152  		if module.HasChild("source") && module.GetAttribute("source").Equals(moduleSource) {
   153  			results = append(results, module)
   154  		}
   155  	}
   156  	return results, nil
   157  }
   158  
   159  func (c *Module) GetReferencingBlocks(originalBlock *Block, referencingType string, referencingLabel string, referencingAttributeName string) Blocks {
   160  	blocks := c.getBlocksByType(referencingType, referencingLabel)
   161  	var results Blocks
   162  	for _, block := range blocks {
   163  		attr := block.GetAttribute(referencingAttributeName)
   164  		if attr == nil {
   165  			continue
   166  		}
   167  		if attr.References(originalBlock.reference) {
   168  			results = append(results, block)
   169  		} else {
   170  			for _, ref := range attr.AllReferences() {
   171  				if ref.TypeLabel() == "each" {
   172  					fe := block.GetAttribute("for_each")
   173  					if fe.References(originalBlock.reference) {
   174  						results = append(results, block)
   175  					}
   176  				}
   177  			}
   178  		}
   179  	}
   180  	return results
   181  }