Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resource type attribute changes and stability fixes for yaml parsing and other config changes APE-16695, APE-16692, APE-16734 #1673

Merged
merged 42 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0366569
fix for crash in lambda function cft yaml if code key is not present
nmoretenable Nov 23, 2023
8190d1c
Merge branch 'tenable:master' into master
nmoretenable Nov 29, 2023
f5cb7e0
removed duplicate tag image tag
nmoretenable Nov 29, 2023
035d90e
Merge branch 'tenable:master' into master
nmoretenable Nov 30, 2023
679e8c5
bump up the version to 1.18.5
nmoretenable Nov 30, 2023
ba6788d
Merge branch 'tenable:master' into master
nmoretenable Dec 13, 2023
c60bcf6
added feature to parse cft template for ssm parameter
nmoretenable Dec 13, 2023
a155718
Merge branch 'tenable:master' into master
nmoretenable Dec 14, 2023
eaee8d2
bumped the version to 1.18.7
nmoretenable Dec 14, 2023
94498ce
Merge branch 'tenable:master' into master
nmoretenable Dec 14, 2023
6fe4ce1
bump up version to v1.18.8
nmoretenable Dec 14, 2023
8801d86
Sanitize the cft template file for aws:: words as it causes parser to…
nmoretenable Dec 18, 2023
55aa326
Sanitize the cft template file for aws:: words as it causes parser to…
nmoretenable Dec 18, 2023
de1b1d9
increment version
nmoretenable Dec 18, 2023
42c1247
Merge branch 'master' into master
nmoretenable Dec 18, 2023
23b982a
Merge branch 'tenable:master' into master
nmoretenable Dec 19, 2023
b82bfef
Merge branch 'tenable:master' into master
nmoretenable Jan 10, 2024
ca48618
APE-16518 - improve the stability of yaml to json parsing
nmoretenable Jan 29, 2024
fc23954
Fixed indirect resource id reference and rds-cluster and restapi for …
nmoretenable Feb 20, 2024
0ba7557
add resource references for json format
nmoretenable Feb 21, 2024
5721350
terraform resource type names added
nmoretenable Feb 22, 2024
a5dee87
terraform res type names added for reference
nmoretenable Feb 22, 2024
83cc390
fixed lint errors for comments
nmoretenable Feb 22, 2024
a199bb6
tags name added as per terraform structure
nmoretenable Feb 26, 2024
ce39c36
lint fixes
nmoretenable Feb 26, 2024
ebad89f
add dynamodb BillingMode property
nmoretenable Feb 27, 2024
ca29cf4
fixed lint error
nmoretenable Feb 28, 2024
4e0a68b
added CrossZoneLoadBalancing for lb
nmoretenable Feb 28, 2024
da63a27
Merge branch 'master' into bugfix/addRemediationaws
nmoretenable Feb 28, 2024
3b77a8e
load balancer lb added
nmoretenable Mar 1, 2024
1c37771
Merge branch 'tenable:master' into master
nmoretenable Mar 1, 2024
9266951
Merge branch 'master' into nmoreterrascanrelease
nmoretenable Mar 1, 2024
8f50647
fixing lint errors
nmoretenable Mar 1, 2024
d7f196b
APE-16777 APE-16773 fixed attribute as per normalize json
prai80 Mar 4, 2024
976324c
merge nmore release branch
prai80 Mar 4, 2024
38eec3a
fix lint
prai80 Mar 4, 2024
abc7c5b
Update ecs-service.go
prai80 Mar 4, 2024
874910e
Update ecs-service.go
prai80 Mar 4, 2024
5f17193
Update ecs-service.go
prai80 Mar 4, 2024
75b4270
Merge pull request #1 from nmoretenable/APE-16777-bucket
nmoretenable Mar 4, 2024
65a4c3f
sonar issue resolved
nmoretenable Mar 7, 2024
ea7113a
sonar issue resolved
nmoretenable Mar 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pkg/iac-providers/cft/v1/load-file.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func (a *CFTV1) extractTemplate(file string, data *[]byte) (*cloudformation.Temp
}

zap.S().Debug("sanitizing cft template file", zap.String("file", file))
sanitized, err := a.sanitizeCftTemplate(*data, isYaml)
sanitized, err := a.sanitizeCftTemplate(file, *data, isYaml)
if err != nil {
zap.S().Debug("failed to sanitize cft template file", zap.String("file", file), zap.Error(err))
return nil, err
Expand Down Expand Up @@ -219,7 +219,7 @@ func (*CFTV1) getFileType(file string, data *[]byte) string {
if isJSON(string(*data)) {
return JSONExtension
}
return YAMLExtension
return TXTExtension
}
return UnknownExtension
}
Expand Down
171 changes: 156 additions & 15 deletions pkg/iac-providers/cft/v1/sanitize-cft-template.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,31 +36,58 @@ const PARAMETERS = "Parameters"
// RESOURCES is a constant to fetch Resources from CFT
const RESOURCES = "Resources"

func (a *CFTV1) sanitizeCftTemplate(data []byte, isYAML bool) (map[string]interface{}, error) {
func (a *CFTV1) sanitizeCftTemplate(fileName string, data []byte, isYAML bool) (map[string]interface{}, error) {
var (
intrinsified []byte
err error
)

if isYAML {
data, err = removeRefAnchors(data)
if err != nil {
return nil, err
}
fallbackToDefaultProcessing := false

// Process all AWS CloudFormation intrinsic functions (e.g. Fn::Join)
intrinsified, err = intrinsics.ProcessYAML(data, nil)
if err != nil {
return nil, fmt.Errorf("error while resolving intrinsic functions, error %w", err)
for i := 0; i < 1; i++ {
// convert the yaml into json
jsonData, err := a.ReadYAMLFileIntoJSON(fileName)
if err == nil {
jsonData, err := a.resolveResourceIDs(jsonData)
if err != nil {
zap.S().Debug(fmt.Sprintf("error while resolving Resource IDs, error %s", err.Error()))
fallbackToDefaultProcessing = true
break
}
intrinsified, err = intrinsics.ProcessJSON(jsonData, nil)
if err != nil {
zap.S().Debug(fmt.Sprintf("error while resolving Resource IDs, error %s", err.Error()))
fallbackToDefaultProcessing = true
break
}
}
}
if fallbackToDefaultProcessing || len(intrinsified) == 0 { // fallback to default behaviour of yaml processing
data, err = removeRefAnchors(data)
if err != nil {
return nil, err
}
// Process all AWS CloudFormation intrinsic functions (e.g. Fn::Join)
intrinsified, err = intrinsics.ProcessYAML(data, nil)
if err != nil {
return nil, fmt.Errorf("error while resolving intrinsic functions, error %w", err)
}
}
} else {
// Process all AWS CloudFormation intrinsic functions (e.g. Fn::Join)
intrinsified, err = intrinsics.ProcessJSON(data, nil)
if err != nil {
return nil, fmt.Errorf("error while resolving intrinsic functions, error %w", err)
jsonData, err := a.resolveResourceIDs(data)
if err == nil {
intrinsified, err = intrinsics.ProcessJSON(jsonData, nil)
if err != nil {
return nil, fmt.Errorf("error while resolving intrinsic functions, error %w", err)
}
} else {
// Process all AWS CloudFormation intrinsic functions (e.g. Fn::Join)
intrinsified, err = intrinsics.ProcessJSON(data, nil)
if err != nil {
return nil, fmt.Errorf("error while resolving intrinsic functions, error %w", err)
}
}
}

templateFileMap := make(map[string]interface{})

err = json.Unmarshal(intrinsified, &templateFileMap)
Expand Down Expand Up @@ -510,3 +537,117 @@ func findKeyAndReplace(obj interface{}, propValues map[string]interface{}) (inte
}
return nil, false
}

// ReadYAMLFileIntoJSON converts the given file into JSON string
func (a *CFTV1) ReadYAMLFileIntoJSON(fileName string) ([]byte, error) {
templateSample, err := a.File(fileName)
if err != nil {
return nil, err
}
gostruct, err := templateSample.Map()
if err != nil {
zap.S().Errorf("failed to map yaml to json. error : %s in file %s", err.Error(), fileName)
return nil, err
}
jsonData, err := json.Marshal(gostruct)
if err != nil {
zap.S().Errorf("failed to convert yaml to json. error : %s", err.Error())
return nil, err
}
return jsonData, nil
}
func (a *CFTV1) getMapOfResourceIds(allData interface{}) map[string]string {
mapOfresourceIds := make(map[string]string)
mapOfParameters := make(map[string]interface{})
if templateFileMap, ok := allData.(map[string]interface{}); ok {
r, ok := templateFileMap[PARAMETERS]
if ok {
rMap, ok := r.(map[string]interface{})
if ok {
for rName, val := range rMap {
zap.S().Debug("inspecting resource", zap.String("Parameters Name", rName))
if val1, ok := val.(map[string]interface{}); ok {
mapOfParameters[rName] = val1["Default"]
}
}
}
}
}

if templateFileMap, ok := allData.(map[string]interface{}); ok {
r, ok := templateFileMap[RESOURCES]
if ok {
rMap, ok := r.(map[string]interface{})
if ok {
for rName := range rMap {
zap.S().Debug("inspecting resource", zap.String("Resource Name", rName))
if _, ok := mapOfParameters[rName]; !ok {
mapOfresourceIds[rName] = rName
}
}
}
}
}
return mapOfresourceIds
}

// resolveResourceIDs resolves the indirect resource to resource references
func (a *CFTV1) resolveResourceIDs(jsonData []byte) ([]byte, error) {
var unmarshalled interface{}
if err := json.Unmarshal(jsonData, &unmarshalled); err != nil {
return nil, fmt.Errorf("invalid JSON: %s", err)
}
mapOfparentReferences := a.getMapOfResourceIds(unmarshalled)
unmarshalledResult := a.resolveIndirectReferences(nil, unmarshalled, "", mapOfparentReferences)
resultBytes, err := json.Marshal(unmarshalledResult)
if err != nil {
return nil, fmt.Errorf("invalid JSON: %s", err)
}
jsonData = resultBytes
return jsonData, nil
}

// resolveIndirectReferences finds if the references are of the Name of the resource and replace it with actual Name
func (a *CFTV1) resolveIndirectReferences(parent interface{}, input interface{}, parentKey string, mapOfReferences map[string]string) interface{} {

switch value := input.(type) {

case map[string]interface{}:
processed := map[string]interface{}{}
for key, val := range value {
if key == "Ref" && parentKey != "" {
valuStr := fmt.Sprintf("%v", val)
if _, ok := mapOfReferences[valuStr]; ok {
if parentVal, ok := parent.(map[string]interface{}); ok {
parentVal[parentKey] = valuStr
val = valuStr
return val
}
}
}
processed[key] = a.resolveIndirectReferences(value, val, key, mapOfReferences)
}
return processed

case []interface{}:

// We found an array in the JSON - recurse through it's elements looking for intrinsic functions
processed := []interface{}{}
for _, val := range value {
processed = append(processed, a.resolveIndirectReferences(parent, val, parentKey, mapOfReferences))
}
return processed

case nil:
return value
case bool:
return value
case float64:
return value
case string:
return value
default:
return nil

}
}
2 changes: 1 addition & 1 deletion pkg/iac-providers/cft/v1/sanitize-cft-template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func TestCFTV1_sanitizeCftTemplate(t *testing.T) {
t.Error("CFTV1.sanitizeCftTemplate() got no error, expected parsing error")
}

templateMap, err := a.sanitizeCftTemplate(data, tt.args.isYAML)
templateMap, err := a.sanitizeCftTemplate(tt.inputFile, data, tt.args.isYAML)
if (err != nil) != tt.wantErr {
t.Errorf("CFTV1.sanitizeCftTemplate() error = %v, wantErr %v", err, tt.wantErr)
return
Expand Down
2 changes: 1 addition & 1 deletion pkg/iac-providers/cft/v1/testdata/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ Resources:
Statement:
- Effect: Allow
Action: *
Principal: '*'
Principal: 'star'

Loading
Loading