driftctl/pkg/middlewares/aws_network_acl_expander.go

111 lines
3.2 KiB
Go

package middlewares
import (
"github.com/snyk/driftctl/pkg/resource"
"github.com/snyk/driftctl/pkg/resource/aws"
)
// This middelware goal is to explode aws_network_acl ingress and egress block into a set of aws_network_acl_rule
type AwsNetworkACLExpander struct {
resourceFactory resource.ResourceFactory
}
func NewAwsNetworkACLExpander(resourceFactory resource.ResourceFactory) AwsNetworkACLExpander {
return AwsNetworkACLExpander{resourceFactory}
}
func (m AwsNetworkACLExpander) Execute(remoteResources, resourcesFromState *[]*resource.Resource) error {
newResourcesFromState := make([]*resource.Resource, 0, len(*resourcesFromState))
for _, stateResource := range *resourcesFromState {
// Ignore all resources other than network acl
if stateResource.ResourceType() != aws.AwsNetworkACLResourceType &&
stateResource.ResourceType() != aws.AwsDefaultNetworkACLResourceType {
newResourcesFromState = append(newResourcesFromState, stateResource)
continue
}
newResourcesFromState = append(newResourcesFromState, m.expandBlock(
resourcesFromState,
stateResource.ResourceId(),
false,
stateResource.Attrs.GetSlice("ingress"),
)...)
stateResource.Attrs.SafeDelete([]string{"ingress"})
newResourcesFromState = append(newResourcesFromState, m.expandBlock(
resourcesFromState,
stateResource.ResourceId(),
true,
stateResource.Attrs.GetSlice("egress"),
)...)
stateResource.Attrs.SafeDelete([]string{"egress"})
newResourcesFromState = append(newResourcesFromState, stateResource)
}
// Then we need to remove ingress and egress block from remote resource too
newRemoteResources := make([]*resource.Resource, 0, len(*remoteResources))
for _, remoteResource := range *remoteResources {
if remoteResource.ResourceType() != aws.AwsNetworkACLResourceType &&
remoteResource.ResourceType() != aws.AwsDefaultNetworkACLResourceType {
newRemoteResources = append(newRemoteResources, remoteResource)
continue
}
remoteResource.Attrs.SafeDelete([]string{"ingress"})
remoteResource.Attrs.SafeDelete([]string{"egress"})
newRemoteResources = append(newRemoteResources, remoteResource)
}
*resourcesFromState = newResourcesFromState
*remoteResources = newRemoteResources
return nil
}
func (e *AwsNetworkACLExpander) expandBlock(resourcesFromState *[]*resource.Resource, networkAclId string, egress bool, ruleBlock []interface{}) []*resource.Resource {
results := make([]*resource.Resource, 0, len(ruleBlock))
for _, rule := range ruleBlock {
attrs := rule.(map[string]interface{})
attrs["rule_number"] = attrs["rule_no"]
delete(attrs, "rule_no")
attrs["egress"] = egress
attrs["network_acl_id"] = networkAclId
attrs["rule_action"] = attrs["action"]
delete(attrs, "action")
res := e.resourceFactory.CreateAbstractResource(
aws.AwsNetworkACLRuleResourceType,
aws.CreateNetworkACLRuleID(
networkAclId,
int(attrs["rule_number"].(float64)),
egress,
attrs["protocol"].(string),
),
attrs,
)
existInState := false
for _, stateRes := range *resourcesFromState {
if stateRes.Equal(res) {
existInState = true
break
}
}
if !existInState {
results = append(results, res)
}
}
return results
}