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 }