github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/cloud/aws/lambda/adapt.go (about)

     1  package lambda
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/khulnasoft-lab/defsec/pkg/concurrency"
     7  	defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types"
     8  
     9  	lambdaapi "github.com/aws/aws-sdk-go-v2/service/lambda"
    10  	"github.com/aws/aws-sdk-go-v2/service/lambda/types"
    11  	"github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws"
    12  	"github.com/khulnasoft-lab/defsec/pkg/providers/aws/lambda"
    13  	"github.com/khulnasoft-lab/defsec/pkg/state"
    14  	"github.com/liamg/iamgo"
    15  )
    16  
    17  type adapter struct {
    18  	*aws.RootAdapter
    19  	api *lambdaapi.Client
    20  }
    21  
    22  func init() {
    23  	aws.RegisterServiceAdapter(&adapter{})
    24  }
    25  
    26  func (a *adapter) Provider() string {
    27  	return "aws"
    28  }
    29  
    30  func (a *adapter) Name() string {
    31  	return "lambda"
    32  }
    33  
    34  func (a *adapter) Adapt(root *aws.RootAdapter, state *state.State) error {
    35  
    36  	a.RootAdapter = root
    37  	a.api = lambdaapi.NewFromConfig(root.SessionConfig())
    38  	var err error
    39  
    40  	state.AWS.Lambda.Functions, err = a.getFunctions()
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	return nil
    46  }
    47  
    48  func (a *adapter) getFunctions() ([]lambda.Function, error) {
    49  
    50  	a.Tracker().SetServiceLabel(" Discovering functions...")
    51  
    52  	// we're currently only pulling back LIVE versions
    53  	input := &lambdaapi.ListFunctionsInput{
    54  		Marker: nil,
    55  	}
    56  
    57  	var apiFunctions []types.FunctionConfiguration
    58  	for {
    59  		output, err := a.api.ListFunctions(a.Context(), input)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  		apiFunctions = append(apiFunctions, output.Functions...)
    64  		a.Tracker().SetTotalResources(len(apiFunctions))
    65  		if output.NextMarker == nil {
    66  			break
    67  		}
    68  		input.Marker = output.NextMarker
    69  	}
    70  
    71  	a.Tracker().SetServiceLabel("Adapting functions...")
    72  	return concurrency.Adapt(apiFunctions, a.RootAdapter, a.adaptFunction), nil
    73  }
    74  
    75  func (a *adapter) adaptFunction(function types.FunctionConfiguration) (*lambda.Function, error) {
    76  	metadata := a.CreateMetadataFromARN(*function.FunctionArn)
    77  	var tracingMode string
    78  	if function.TracingConfig != nil {
    79  		tracingMode = string(function.TracingConfig.Mode)
    80  	}
    81  
    82  	var permissions []lambda.Permission
    83  	if output, err := a.api.GetPolicy(a.Context(), &lambdaapi.GetPolicyInput{
    84  		FunctionName: function.FunctionName,
    85  		Qualifier:    function.Version,
    86  	}); err == nil {
    87  		parsed, err := iamgo.ParseString(*output.Policy)
    88  		if err != nil {
    89  			return nil, err
    90  		}
    91  		statements, _ := parsed.Statements()
    92  		for _, statement := range statements {
    93  
    94  			var principal string
    95  			principals, _ := statement.Principals()
    96  			if awsPrincipals, _ := principals.AWS(); len(awsPrincipals) > 0 {
    97  				principal = awsPrincipals[0]
    98  			} else if svcPrincipals, _ := principals.Service(); len(svcPrincipals) > 0 {
    99  				principal = svcPrincipals[0]
   100  			}
   101  
   102  			var source string
   103  			conditions, _ := statement.Conditions()
   104  			for _, condition := range conditions {
   105  				operator, _ := condition.Operator()
   106  				key, _ := condition.Key()
   107  				values, _ := condition.Value()
   108  				if len(values) == 0 {
   109  					continue
   110  				}
   111  				switch {
   112  				case strings.EqualFold(operator, "StringEquals") && strings.EqualFold(key, "AWS:SourceAccount"):
   113  					source = values[0]
   114  				case strings.EqualFold(operator, "ArnLike") && strings.EqualFold(key, "AWS:SourceArn"):
   115  					source = values[0]
   116  				}
   117  			}
   118  
   119  			permissions = append(permissions, lambda.Permission{
   120  				Metadata:  metadata,
   121  				Principal: defsecTypes.String(principal, metadata),
   122  				SourceARN: defsecTypes.String(source, metadata),
   123  			})
   124  		}
   125  	}
   126  
   127  	return &lambda.Function{
   128  		Metadata: metadata,
   129  		Tracing: lambda.Tracing{
   130  			Metadata: metadata,
   131  			Mode:     defsecTypes.String(tracingMode, metadata),
   132  		},
   133  		Permissions: permissions,
   134  	}, nil
   135  }