github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/internal/adapters/cloud/aws/ec2/ec2.go (about) 1 package ec2 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/aws/aws-sdk-go-v2/aws" 8 "github.com/khulnasoft-lab/defsec/pkg/concurrency" 9 defsecTypes "github.com/khulnasoft-lab/defsec/pkg/types" 10 11 ec2api "github.com/aws/aws-sdk-go-v2/service/ec2" 12 ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types" 13 aws2 "github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws" 14 "github.com/khulnasoft-lab/defsec/pkg/providers/aws/ec2" 15 "github.com/khulnasoft-lab/defsec/pkg/state" 16 ) 17 18 type adapter struct { 19 *aws2.RootAdapter 20 client *ec2api.Client 21 } 22 23 func init() { 24 aws2.RegisterServiceAdapter(&adapter{}) 25 } 26 27 func (a *adapter) Provider() string { 28 return "aws" 29 } 30 31 func (a *adapter) Name() string { 32 return "ec2" 33 } 34 35 func (a *adapter) Adapt(root *aws2.RootAdapter, state *state.State) error { 36 37 a.RootAdapter = root 38 a.client = ec2api.NewFromConfig(root.SessionConfig()) 39 var err error 40 41 state.AWS.EC2.Instances, err = a.getInstances() 42 if err != nil { 43 return err 44 } 45 46 state.AWS.EC2.SecurityGroups, err = a.getSecurityGroups() 47 if err != nil { 48 return err 49 } 50 51 state.AWS.EC2.NetworkACLs, err = a.getNetworkACLs() 52 if err != nil { 53 return err 54 } 55 56 state.AWS.EC2.VPCs, err = a.getVPCs() 57 if err != nil { 58 return err 59 } 60 61 state.AWS.EC2.LaunchTemplates, err = a.getLaunchTemplates() 62 if err != nil { 63 return err 64 } 65 66 state.AWS.EC2.Volumes, err = a.getVolumes() 67 if err != nil { 68 return err 69 } 70 71 for i, vpc := range state.AWS.EC2.VPCs { 72 for _, group := range state.AWS.EC2.SecurityGroups { 73 if group.VPCID.EqualTo(vpc.ID.Value()) { 74 state.AWS.EC2.VPCs[i].SecurityGroups = append(state.AWS.EC2.VPCs[i].SecurityGroups, group) 75 } 76 } 77 } 78 79 return nil 80 } 81 82 func (a *adapter) getInstances() (instances []ec2.Instance, err error) { 83 84 a.Tracker().SetServiceLabel("Discovering instances...") 85 var apiInstances []ec2Types.Instance 86 input := &ec2api.DescribeInstancesInput{ 87 Filters: []ec2Types.Filter{ 88 { 89 Name: aws.String("instance-state-name"), 90 Values: []string{"running"}, 91 }, 92 }, 93 } 94 95 for { 96 output, err := a.client.DescribeInstances(a.Context(), input) 97 if err != nil { 98 return nil, err 99 } 100 for _, res := range output.Reservations { 101 apiInstances = append(apiInstances, res.Instances...) 102 } 103 104 a.Tracker().SetTotalResources(len(apiInstances)) 105 if output.NextToken == nil { 106 break 107 } 108 input.NextToken = output.NextToken 109 } 110 111 a.Tracker().SetServiceLabel("Adapting instances...") 112 return concurrency.Adapt(apiInstances, a.RootAdapter, a.adaptInstance), nil 113 } 114 115 func (a *adapter) adaptInstance(instance ec2Types.Instance) (*ec2.Instance, error) { 116 117 volumeBlockMap := make(map[string]*ec2.BlockDevice) 118 var volumeIds []string 119 instanceMetadata := a.CreateMetadata("instance/" + *instance.InstanceId) 120 121 i := ec2.NewInstance(instanceMetadata) 122 if instance.MetadataOptions != nil { 123 i.MetadataOptions.HttpTokens = defsecTypes.StringDefault(string(instance.MetadataOptions.HttpTokens), instanceMetadata) 124 i.MetadataOptions.HttpEndpoint = defsecTypes.StringDefault(string(instance.MetadataOptions.HttpEndpoint), instanceMetadata) 125 } 126 127 if instance.BlockDeviceMappings != nil { 128 for _, blockMapping := range instance.BlockDeviceMappings { 129 volumeMetadata := a.CreateMetadata(fmt.Sprintf("volume/%s", *blockMapping.Ebs.VolumeId)) 130 ebsDevice := &ec2.BlockDevice{ 131 Metadata: volumeMetadata, 132 Encrypted: defsecTypes.BoolDefault(false, volumeMetadata), 133 } 134 if strings.EqualFold(*blockMapping.DeviceName, *instance.RootDeviceName) { 135 // is root block device 136 i.RootBlockDevice = ebsDevice 137 } else { 138 i.EBSBlockDevices = append(i.EBSBlockDevices, ebsDevice) 139 } 140 volumeBlockMap[*blockMapping.Ebs.VolumeId] = ebsDevice 141 volumeIds = append(volumeIds, *blockMapping.Ebs.VolumeId) 142 } 143 } 144 145 volumes, err := a.client.DescribeVolumes(a.Context(), &ec2api.DescribeVolumesInput{ 146 VolumeIds: volumeIds, 147 }) 148 if err != nil { 149 return nil, err 150 } 151 152 for _, v := range volumes.Volumes { 153 block := volumeBlockMap[*v.VolumeId] 154 if block != nil { 155 block.Encrypted = defsecTypes.BoolDefault(false, block.Metadata) 156 if v.Encrypted != nil { 157 block.Encrypted = defsecTypes.Bool(*v.Encrypted, block.Metadata) 158 } 159 } 160 } 161 return i, nil 162 }