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 }