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

     1  package ec2
     2  
     3  import (
     4  	"github.com/aws/aws-sdk-go-v2/aws"
     5  	ec2api "github.com/aws/aws-sdk-go-v2/service/ec2"
     6  	ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
     7  	"github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws/test"
     8  	"github.com/khulnasoft-lab/defsec/pkg/state"
     9  	"github.com/stretchr/testify/assert"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"testing"
    13  
    14  	aws2 "github.com/khulnasoft-lab/defsec/internal/adapters/cloud/aws"
    15  )
    16  
    17  type volumeDetails struct {
    18  	encrypted bool
    19  	size      int32
    20  }
    21  
    22  type instanceDetails struct {
    23  	rootVolume *volumeDetails
    24  	ebsVolume  []volumeDetails
    25  }
    26  
    27  func Test_EC2RootVolumeEncrypted(t *testing.T) {
    28  
    29  	tests := []struct {
    30  		name    string
    31  		details instanceDetails
    32  	}{
    33  		{
    34  			name: "simple instance with root volume encryption",
    35  			details: instanceDetails{
    36  				rootVolume: &volumeDetails{
    37  					encrypted: true,
    38  					size:      10,
    39  				},
    40  			},
    41  		},
    42  		{
    43  			name: "simple instance with no root volume encryption",
    44  			details: instanceDetails{
    45  				rootVolume: &volumeDetails{
    46  					encrypted: false,
    47  					size:      10,
    48  				},
    49  			},
    50  		},
    51  		{
    52  			name: "simple instance with root volume encryption and an encrypted ebs volume",
    53  			details: instanceDetails{
    54  				rootVolume: &volumeDetails{
    55  					encrypted: false,
    56  					size:      10,
    57  				},
    58  				ebsVolume: []volumeDetails{
    59  					{
    60  						encrypted: true,
    61  						size:      10,
    62  					},
    63  				},
    64  			},
    65  		},
    66  		{
    67  			name: "simple instance with root volume encryption and an unencrypted ebs volume",
    68  			details: instanceDetails{
    69  				rootVolume: &volumeDetails{
    70  					encrypted: false,
    71  					size:      10,
    72  				},
    73  				ebsVolume: []volumeDetails{
    74  					{
    75  						encrypted: false,
    76  						size:      10,
    77  					},
    78  				},
    79  			},
    80  		},
    81  	}
    82  
    83  	ra, stack, err := test.CreateLocalstackAdapter(t)
    84  	defer func() { _ = stack.Stop() }()
    85  	require.NoError(t, err)
    86  
    87  	for _, tt := range tests {
    88  		t.Run(tt.name, func(t *testing.T) {
    89  			instanceID := bootstrapEC2Instance(t, ra, tt.details)
    90  
    91  			testState := &state.State{}
    92  			ec2Adapter := &adapter{}
    93  			err = ec2Adapter.Adapt(ra, testState)
    94  			require.NoError(t, err)
    95  
    96  			assert.Len(t, testState.AWS.EC2.Instances, 1)
    97  			got := testState.AWS.EC2.Instances[0]
    98  
    99  			if tt.details.rootVolume != nil {
   100  				require.NotNil(t, got.RootBlockDevice)
   101  				assert.Equal(t, tt.details.rootVolume.encrypted, got.RootBlockDevice.Encrypted.Value())
   102  			} else {
   103  				require.Nil(t, got.RootBlockDevice)
   104  			}
   105  
   106  			if len(tt.details.ebsVolume) > 0 {
   107  				require.Len(t, got.EBSBlockDevices, len(tt.details.ebsVolume))
   108  				assert.Equal(t, tt.details.ebsVolume[0].encrypted, got.EBSBlockDevices[0].Encrypted.Value())
   109  			} else {
   110  				require.Len(t, got.EBSBlockDevices, 0)
   111  			}
   112  			removeInstance(t, ra, instanceID)
   113  		})
   114  	}
   115  }
   116  
   117  func bootstrapEC2Instance(t *testing.T, ra *aws2.RootAdapter, spec instanceDetails) *string {
   118  
   119  	api := ec2api.NewFromConfig(ra.SessionConfig())
   120  
   121  	var blockMappings []ec2Types.BlockDeviceMapping
   122  
   123  	if spec.rootVolume != nil {
   124  		blockMappings = bootstrapVolume(blockMappings, "/dev/sda1", *spec.rootVolume)
   125  	}
   126  
   127  	for _, ebs := range spec.ebsVolume {
   128  		blockMappings = bootstrapVolume(blockMappings, "/dev/xvd", ebs)
   129  	}
   130  
   131  	instanceResp, err := api.RunInstances(ra.Context(), &ec2api.RunInstancesInput{
   132  		ImageId:             aws.String("ami-0b9c9f62b6a9b7c7a"),
   133  		MinCount:            aws.Int32(1),
   134  		MaxCount:            aws.Int32(1),
   135  		BlockDeviceMappings: blockMappings,
   136  	})
   137  	require.NoError(t, err)
   138  
   139  	return instanceResp.Instances[0].InstanceId
   140  }
   141  
   142  func bootstrapVolume(blockMappings []ec2Types.BlockDeviceMapping, deviceName string, volume volumeDetails) []ec2Types.BlockDeviceMapping {
   143  	blockMappings = append(blockMappings, ec2Types.BlockDeviceMapping{
   144  		DeviceName: aws.String(deviceName),
   145  		Ebs: &ec2Types.EbsBlockDevice{
   146  			Encrypted:           aws.Bool(volume.encrypted),
   147  			VolumeSize:          aws.Int32(volume.size),
   148  			DeleteOnTermination: aws.Bool(true),
   149  		},
   150  	})
   151  	return blockMappings
   152  }
   153  
   154  func removeInstance(t *testing.T, ra *aws2.RootAdapter, instanceID *string) {
   155  
   156  	api := ec2api.NewFromConfig(ra.SessionConfig())
   157  
   158  	_, err := api.TerminateInstances(ra.Context(), &ec2api.TerminateInstancesInput{
   159  		InstanceIds: []string{*instanceID},
   160  	})
   161  	require.NoError(t, err)
   162  }