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

     1  package elasticache
     2  
     3  import (
     4  	api "github.com/aws/aws-sdk-go-v2/service/elasticache"
     5  	"github.com/aws/aws-sdk-go-v2/service/elasticache/types"
     6  	"github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws"
     7  	"github.com/khulnasoft-lab/defsec/pkg/concurrency"
     8  	"github.com/khulnasoft-lab/defsec/pkg/providers/aws/elasticache"
     9  	"github.com/khulnasoft-lab/defsec/pkg/state"
    10  	defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types"
    11  )
    12  
    13  type adapter struct {
    14  	*aws.RootAdapter
    15  	api *api.Client
    16  }
    17  
    18  func init() {
    19  	aws.RegisterServiceAdapter(&adapter{})
    20  }
    21  
    22  func (a *adapter) Provider() string {
    23  	return "aws"
    24  }
    25  
    26  func (a *adapter) Name() string {
    27  	return "elasticache"
    28  }
    29  
    30  func (a *adapter) Adapt(root *aws.RootAdapter, state *state.State) error {
    31  
    32  	a.RootAdapter = root
    33  	a.api = api.NewFromConfig(root.SessionConfig())
    34  	var err error
    35  
    36  	state.AWS.ElastiCache.Clusters, err = a.getClusters()
    37  	if err != nil {
    38  		return err
    39  	}
    40  
    41  	state.AWS.ElastiCache.ReplicationGroups, err = a.getReplicationGroups()
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	// this can error if classic resources are requested where not available
    47  	state.AWS.ElastiCache.SecurityGroups, _ = a.getSecurityGroups()
    48  
    49  	return nil
    50  }
    51  
    52  func (a *adapter) getClusters() ([]elasticache.Cluster, error) {
    53  
    54  	a.Tracker().SetServiceLabel("Discovering clusters...")
    55  
    56  	var input api.DescribeCacheClustersInput
    57  	var apiClusters []types.CacheCluster
    58  	for {
    59  		output, err := a.api.DescribeCacheClusters(a.Context(), &input)
    60  		if err != nil {
    61  			return nil, err
    62  		}
    63  		apiClusters = append(apiClusters, output.CacheClusters...)
    64  		a.Tracker().SetTotalResources(len(apiClusters))
    65  		if output.Marker == nil {
    66  			break
    67  		}
    68  		input.Marker = output.Marker
    69  	}
    70  
    71  	a.Tracker().SetServiceLabel("Adapting clusters...")
    72  	return concurrency.Adapt(apiClusters, a.RootAdapter, a.adaptCluster), nil
    73  }
    74  
    75  func (a *adapter) adaptCluster(apiCluster types.CacheCluster) (*elasticache.Cluster, error) {
    76  	metadata := a.CreateMetadataFromARN(*apiCluster.ARN)
    77  
    78  	engine := defsecTypes.StringDefault("", metadata)
    79  	if apiCluster.Engine != nil {
    80  		engine = defsecTypes.String(*apiCluster.Engine, metadata)
    81  	}
    82  
    83  	nodeType := defsecTypes.StringDefault("", metadata)
    84  	if apiCluster.CacheNodeType != nil {
    85  		nodeType = defsecTypes.String(*apiCluster.CacheNodeType, metadata)
    86  	}
    87  
    88  	limit := defsecTypes.IntDefault(0, metadata)
    89  	if apiCluster.SnapshotRetentionLimit != nil {
    90  		limit = defsecTypes.Int(int(*apiCluster.SnapshotRetentionLimit), metadata)
    91  	}
    92  
    93  	return &elasticache.Cluster{
    94  		Metadata:               metadata,
    95  		Engine:                 engine,
    96  		NodeType:               nodeType,
    97  		SnapshotRetentionLimit: limit,
    98  	}, nil
    99  }
   100  
   101  func (a *adapter) getReplicationGroups() ([]elasticache.ReplicationGroup, error) {
   102  
   103  	a.Tracker().SetServiceLabel("Discovering replication groups...")
   104  
   105  	var input api.DescribeReplicationGroupsInput
   106  	var apiGroups []types.ReplicationGroup
   107  	for {
   108  		output, err := a.api.DescribeReplicationGroups(a.Context(), &input)
   109  		if err != nil {
   110  			return nil, err
   111  		}
   112  		apiGroups = append(apiGroups, output.ReplicationGroups...)
   113  		a.Tracker().SetTotalResources(len(apiGroups))
   114  		if output.Marker == nil {
   115  			break
   116  		}
   117  		input.Marker = output.Marker
   118  	}
   119  
   120  	a.Tracker().SetServiceLabel("Adapting replication groups...")
   121  
   122  	var groups []elasticache.ReplicationGroup
   123  	for _, apiGroup := range apiGroups {
   124  		group, err := a.adaptReplicationGroup(apiGroup)
   125  		if err != nil {
   126  			a.Debug("Failed to adapt replication group '%s': %s", *apiGroup.ARN, err)
   127  			continue
   128  		}
   129  		groups = append(groups, *group)
   130  		a.Tracker().IncrementResource()
   131  	}
   132  
   133  	return groups, nil
   134  }
   135  
   136  func (a *adapter) adaptReplicationGroup(apiGroup types.ReplicationGroup) (*elasticache.ReplicationGroup, error) {
   137  	metadata := a.CreateMetadataFromARN(*apiGroup.ARN)
   138  
   139  	transitEncrypted := defsecTypes.BoolDefault(false, metadata)
   140  	if apiGroup.TransitEncryptionEnabled != nil {
   141  		transitEncrypted = defsecTypes.Bool(*apiGroup.TransitEncryptionEnabled, metadata)
   142  	}
   143  	atRestEncrypted := defsecTypes.BoolDefault(false, metadata)
   144  	if apiGroup.AtRestEncryptionEnabled != nil {
   145  		atRestEncrypted = defsecTypes.Bool(*apiGroup.AtRestEncryptionEnabled, metadata)
   146  	}
   147  
   148  	return &elasticache.ReplicationGroup{
   149  		Metadata:                 metadata,
   150  		TransitEncryptionEnabled: transitEncrypted,
   151  		AtRestEncryptionEnabled:  atRestEncrypted,
   152  	}, nil
   153  }
   154  
   155  func (a *adapter) getSecurityGroups() ([]elasticache.SecurityGroup, error) {
   156  
   157  	a.Tracker().SetServiceLabel("Discovering security groups...")
   158  
   159  	var input api.DescribeCacheSecurityGroupsInput
   160  	var apiGroups []types.CacheSecurityGroup
   161  	for {
   162  		output, err := a.api.DescribeCacheSecurityGroups(a.Context(), &input)
   163  		if err != nil {
   164  			return nil, err
   165  		}
   166  		apiGroups = append(apiGroups, output.CacheSecurityGroups...)
   167  		a.Tracker().SetTotalResources(len(apiGroups))
   168  		if output.Marker == nil {
   169  			break
   170  		}
   171  		input.Marker = output.Marker
   172  	}
   173  
   174  	a.Tracker().SetServiceLabel("Adapting security groups...")
   175  
   176  	var groups []elasticache.SecurityGroup
   177  	for _, apiGroup := range apiGroups {
   178  		group, err := a.adaptSecurityGroup(apiGroup)
   179  		if err != nil {
   180  			a.Debug("Failed to adapt security group '%s': %s", *apiGroup.ARN, err)
   181  			continue
   182  		}
   183  		groups = append(groups, *group)
   184  		a.Tracker().IncrementResource()
   185  	}
   186  
   187  	return groups, nil
   188  }
   189  
   190  func (a *adapter) adaptSecurityGroup(apiGroup types.CacheSecurityGroup) (*elasticache.SecurityGroup, error) {
   191  	metadata := a.CreateMetadataFromARN(*apiGroup.ARN)
   192  	description := defsecTypes.StringDefault("", metadata)
   193  	if apiGroup.Description != nil {
   194  		description = defsecTypes.String(*apiGroup.Description, metadata)
   195  	}
   196  	return &elasticache.SecurityGroup{
   197  		Metadata:    metadata,
   198  		Description: description,
   199  	}, nil
   200  }