diff --git a/pkg/iac/rego/metadata.go b/pkg/iac/rego/metadata.go index dd2c1f104fc..907b8450bdc 100644 --- a/pkg/iac/rego/metadata.go +++ b/pkg/iac/rego/metadata.go @@ -90,15 +90,7 @@ func (sm *StaticMetadata) Update(meta map[string]any) error { if raw, ok := meta["url"]; ok { sm.References = append(sm.References, fmt.Sprintf("%s", raw)) } - if raw, ok := meta["frameworks"]; ok { - frameworks, ok := raw.(map[string][]string) - if !ok { - return fmt.Errorf("failed to parse framework metadata: not an object") - } - for fw, sections := range frameworks { - sm.Frameworks[framework.Framework(fw)] = sections - } - } + if raw, ok := meta["related_resources"]; ok { switch relatedResources := raw.(type) { case []map[string]any: @@ -112,6 +104,9 @@ func (sm *StaticMetadata) Update(meta map[string]any) error { } } + if err := sm.updateFrameworks(meta); err != nil { + return fmt.Errorf("failed to update frameworks: %w", err) + } sm.updateAliases(meta) var err error @@ -126,6 +121,28 @@ func (sm *StaticMetadata) Update(meta map[string]any) error { return nil } +func (sm *StaticMetadata) updateFrameworks(meta map[string]any) error { + if raw, ok := meta["frameworks"]; ok { + frameworks, ok := raw.(map[string]any) + if !ok { + return fmt.Errorf("frameworks metadata is not an object, got %T", raw) + } + for fw, rawIDs := range frameworks { + ids, ok := rawIDs.([]any) + if !ok { + return fmt.Errorf("framework ids is not an array, got %T", rawIDs) + } + fr := framework.Framework(fw) + for _, id := range ids { + if str, ok := id.(string); ok { + sm.Frameworks[fr] = append(sm.Frameworks[fr], str) + } + } + } + } + return nil +} + func (sm *StaticMetadata) updateAliases(meta map[string]any) { if raw, ok := meta["aliases"]; ok { if aliases, ok := raw.([]any); ok { @@ -172,8 +189,15 @@ func NewEngineMetadata(schema string, meta map[string]any) (*scan.EngineMetadata if val, ok := sMap["bad_examples"].(string); ok { em.BadExamples = []string{val} } - if val, ok := sMap["links"].(string); ok { - em.Links = []string{val} + switch links := sMap["links"].(type) { + case string: + em.Links = []string{links} + case []any: + for _, v := range links { + if str, ok := v.(string); ok { + em.Links = append(em.Links, str) + } + } } if val, ok := sMap["remediation_markdown"].(string); ok { em.RemediationMarkdown = val diff --git a/pkg/iac/rego/metadata_test.go b/pkg/iac/rego/metadata_test.go index 4ef5a717306..6b4bb9773a9 100644 --- a/pkg/iac/rego/metadata_test.go +++ b/pkg/iac/rego/metadata_test.go @@ -46,8 +46,8 @@ func Test_UpdateStaticMetadata(t *testing.T) { "severity": "s_n", "library": true, "url": "r_n", - "frameworks": map[string][]string{ - "all": {"aa"}, + "frameworks": map[string]any{ + "all": []any{"aa"}, }, }, )) @@ -137,7 +137,7 @@ func Test_UpdateStaticMetadata(t *testing.T) { }) } -func Test_getEngineMetadata(t *testing.T) { +func Test_NewEngineMetadata(t *testing.T) { inputSchema := map[string]any{ "terraform": map[string]any{ "good_examples": `resource "aws_cloudtrail" "good_example" { @@ -153,8 +153,11 @@ func Test_getEngineMetadata(t *testing.T) { } } }`, + + "links": "https://avd.aquasec.com/avd/183", }, - "cloud_formation": map[string]any{"good_examples": `--- + "cloud_formation": map[string]any{ + "good_examples": `--- Resources: GoodExample: Type: AWS::CloudTrail::Trail @@ -164,15 +167,19 @@ Resources: S3BucketName: "CloudtrailBucket" S3KeyPrefix: "/trailing" TrailName: "Cloudtrail"`, - }} + "links": []any{"https://avd.aquasec.com/avd/183"}, + }, + } var testCases = []struct { schema string - want string + want *scan.EngineMetadata }{ { schema: "terraform", - want: `resource "aws_cloudtrail" "good_example" { + want: &scan.EngineMetadata{ + GoodExamples: []string{ + `resource "aws_cloudtrail" "good_example" { is_multi_region_trail = true event_selector { @@ -185,9 +192,15 @@ Resources: } } }`, + }, + Links: []string{"https://avd.aquasec.com/avd/183"}, + }, }, - {schema: "cloud_formation", - want: `--- + { + schema: "cloud_formation", + want: &scan.EngineMetadata{ + GoodExamples: []string{ + `--- Resources: GoodExample: Type: AWS::CloudTrail::Trail @@ -196,14 +209,18 @@ Resources: IsMultiRegionTrail: true S3BucketName: "CloudtrailBucket" S3KeyPrefix: "/trailing" - TrailName: "Cloudtrail"`}, + TrailName: "Cloudtrail"`, + }, + Links: []string{"https://avd.aquasec.com/avd/183"}, + }, + }, } for _, tc := range testCases { t.Run(tc.schema, func(t *testing.T) { em, err := NewEngineMetadata(tc.schema, inputSchema) require.NoError(t, err) - assert.Equal(t, tc.want, em.GoodExamples[0]) + assert.Equal(t, tc.want, em) }) } }