feat: add aws_lb & aws_alb

main
sundowndev-snyk 2022-04-07 11:56:02 +04:00
parent 39b0a8a562
commit 523b24f977
No known key found for this signature in database
GPG Key ID: A4A2BE47AC4C6A68
27 changed files with 175577 additions and 3 deletions

View File

@ -124,6 +124,7 @@ func (d DriftCTL) Run() (*analyser.Analysis, error) {
middlewares.NewAwsConsoleApiGatewayGatewayResponse(),
middlewares.NewAwsApiGatewayDomainNamesReconciler(),
middlewares.NewAwsEbsEncryptionByDefaultReconciler(d.resourceFactory),
middlewares.NewAwsALBTransformer(d.resourceFactory),
middlewares.NewGoogleIAMBindingTransformer(d.resourceFactory),
middlewares.NewGoogleIAMPolicyTransformer(d.resourceFactory),

View File

@ -194,6 +194,7 @@ func TestTerraformStateReader_AWS_Resources(t *testing.T) {
{name: "Launch template", dirName: "aws_launch_template", wantErr: false},
{name: "Launch configuration", dirName: "aws_launch_configuration", wantErr: false},
{name: "EBS encryption by default", dirName: "aws_ebs_encryption_by_default", wantErr: false},
{name: "LoadBalancer", dirName: "aws_lb", wantErr: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -0,0 +1,54 @@
[
{
"Id": "arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/test-lb-tf/35be57d467ff22b9",
"Type": "aws_alb",
"Attrs": {
"access_logs": [
{
"bucket": "",
"enabled": false,
"prefix": ""
}
],
"arn": "arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/test-lb-tf/35be57d467ff22b9",
"arn_suffix": "app/test-lb-tf/35be57d467ff22b9",
"customer_owned_ipv4_pool": "",
"dns_name": "test-lb-tf-278241463.us-east-1.elb.amazonaws.com",
"drop_invalid_header_fields": false,
"enable_deletion_protection": false,
"enable_http2": true,
"id": "arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/test-lb-tf/35be57d467ff22b9",
"idle_timeout": 60,
"internal": false,
"ip_address_type": "ipv4",
"load_balancer_type": "application",
"name": "test-lb-tf",
"security_groups": [
"sg-06fecfaa711e65b6c"
],
"subnet_mapping": [
{
"allocation_id": "",
"outpost_id": "",
"private_ipv4_address": "",
"subnet_id": "subnet-003713513d37c0905"
},
{
"allocation_id": "",
"outpost_id": "",
"private_ipv4_address": "",
"subnet_id": "subnet-063162f23053ebfdd"
}
],
"subnets": [
"subnet-003713513d37c0905",
"subnet-063162f23053ebfdd"
],
"tags": {
"Environment": "dev"
},
"vpc_id": "vpc-0ae1f138a09749ef1",
"zone_id": "Z35SXDOTRQ7X7K"
}
}
]

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
{
"version": 4,
"terraform_version": "1.0.0",
"serial": 526,
"lineage": "9566e18d-6080-4aa8-e9a6-4c38905cf68f",
"outputs": {},
"resources": [
{
"mode": "managed",
"type": "aws_alb",
"name": "test",
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
"instances": [
{
"schema_version": 0,
"attributes": {
"access_logs": [
{
"bucket": "",
"enabled": false,
"prefix": ""
}
],
"arn": "arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/test-lb-tf/35be57d467ff22b9",
"arn_suffix": "app/test-lb-tf/35be57d467ff22b9",
"customer_owned_ipv4_pool": "",
"desync_mitigation_mode": "defensive",
"dns_name": "test-lb-tf-278241463.us-east-1.elb.amazonaws.com",
"drop_invalid_header_fields": false,
"enable_cross_zone_load_balancing": null,
"enable_deletion_protection": false,
"enable_http2": true,
"enable_waf_fail_open": false,
"id": "arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/test-lb-tf/35be57d467ff22b9",
"idle_timeout": 60,
"internal": false,
"ip_address_type": "ipv4",
"load_balancer_type": "application",
"name": "test-lb-tf",
"name_prefix": null,
"security_groups": [
"sg-06fecfaa711e65b6c"
],
"subnet_mapping": [
{
"allocation_id": "",
"ipv6_address": "",
"outpost_id": "",
"private_ipv4_address": "",
"subnet_id": "subnet-003713513d37c0905"
},
{
"allocation_id": "",
"ipv6_address": "",
"outpost_id": "",
"private_ipv4_address": "",
"subnet_id": "subnet-063162f23053ebfdd"
}
],
"subnets": [
"subnet-003713513d37c0905",
"subnet-063162f23053ebfdd"
],
"tags": {
"Environment": "dev"
},
"tags_all": {
"Environment": "dev"
},
"timeouts": null,
"vpc_id": "vpc-0ae1f138a09749ef1",
"zone_id": "Z35SXDOTRQ7X7K"
},
"sensitive_attributes": [],
"private": "eyJlMmJmYjczMC1lY2FhLTExZTYtOGY4OC0zNDM2M2JjN2M0YzAiOnsiY3JlYXRlIjo2MDAwMDAwMDAwMDAsImRlbGV0ZSI6NjAwMDAwMDAwMDAwLCJ1cGRhdGUiOjYwMDAwMDAwMDAwMH19",
"dependencies": [
"aws_security_group.lb_sg",
"aws_subnet.main-1",
"aws_subnet.main-2",
"aws_vpc.main"
]
}
]
}
]
}

View File

@ -0,0 +1,39 @@
package middlewares
import (
"github.com/snyk/driftctl/pkg/resource"
"github.com/snyk/driftctl/pkg/resource/aws"
)
// AwsALBTransformer is a simple middleware to turn all aws_alb resources into aws_lb ones
// Both types provide the same functionality, but we can't know which one was used to provision cloud resources.
// So we use aws_lb as the common type.
type AwsALBTransformer struct {
resourceFactory resource.ResourceFactory
}
func NewAwsALBTransformer(resourceFactory resource.ResourceFactory) AwsALBTransformer {
return AwsALBTransformer{
resourceFactory: resourceFactory,
}
}
func (m AwsALBTransformer) Execute(_, resourcesFromState *[]*resource.Resource) error {
newStateResources := make([]*resource.Resource, 0, len(*resourcesFromState))
for _, res := range *resourcesFromState {
if res.ResourceType() != aws.AwsApplicationLoadBalancerResourceType {
newStateResources = append(newStateResources, res)
continue
}
newStateResources = append(newStateResources, m.resourceFactory.CreateAbstractResource(
aws.AwsLoadBalancerResourceType,
res.ResourceId(),
*res.Attributes(),
))
}
*resourcesFromState = newStateResources
return nil
}

View File

@ -0,0 +1,124 @@
package middlewares
import (
"strings"
"testing"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/r3labs/diff/v2"
"github.com/snyk/driftctl/pkg/resource"
"github.com/snyk/driftctl/pkg/resource/aws"
"github.com/snyk/driftctl/pkg/terraform"
)
func TestAwsALBTransformer_Execute(t *testing.T) {
tests := []struct {
name string
resourcesFromState []*resource.Resource
mocks func(*terraform.MockResourceFactory)
expected []*resource.Resource
}{
{
name: "should not transform anything",
mocks: func(factory *terraform.MockResourceFactory) {},
resourcesFromState: []*resource.Resource{
{
Id: "foo",
Type: aws.AwsS3BucketResourceType,
Attrs: &resource.Attributes{},
},
{
Id: "bar",
Type: aws.AwsLoadBalancerResourceType,
Attrs: &resource.Attributes{},
},
},
expected: []*resource.Resource{
{
Id: "foo",
Type: aws.AwsS3BucketResourceType,
Attrs: &resource.Attributes{},
},
{
Id: "bar",
Type: aws.AwsLoadBalancerResourceType,
Attrs: &resource.Attributes{},
},
},
},
{
name: "should transform ALB into LB",
mocks: func(factory *terraform.MockResourceFactory) {
factory.
On("CreateAbstractResource", aws.AwsLoadBalancerResourceType, "alb-test", map[string]interface{}{}).
Return(&resource.Resource{
Id: "alb-test",
Type: aws.AwsLoadBalancerResourceType,
Attrs: &resource.Attributes{},
}).
Once()
},
resourcesFromState: []*resource.Resource{
{
Id: "foo",
Type: aws.AwsApiGatewayRestApiResourceType,
Attrs: &resource.Attributes{
"body": "{\"info\":{\"title\":\"example\",\"version\":\"1.0\"},\"openapi\":\"3.0.1\",\"paths\":{\"/path1\":{\"get\":{\"parameters\":[{\"in\":\"query\",\"name\":\"type\",\"schema\":{\"type\":\"string\"}},{\"in\":\"query\",\"name\":\"page\",\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Pets\"}}},\"description\":\"200 response\",\"headers\":{\"Access-Control-Allow-Origin\":{\"schema\":{\"type\":\"string\"}}}}},\"x-amazon-apigateway-integration\":{\"httpMethod\":\"GET\",\"payloadFormatVersion\":\"1.0\",\"type\":\"HTTP_PROXY\",\"uri\":\"https://ip-ranges.amazonaws.com/ip-ranges.json\",\"responses\":{\"2\\\\d{2}\":{\"responseTemplates\":{\"application/json\":\"#set ($root=$input.path('$')) { \\\"stage\\\": \\\"$root.name\\\", \\\"user-id\\\": \\\"$root.key\\\" }\",\"application/xml\":\"#set ($root=$input.path('$')) \\u003cstage\\u003e$root.name\\u003c/stage\\u003e \"},\"statusCode\":\"200\"}}}}},\"/path1/path2\":{\"get\":{\"x-amazon-apigateway-integration\":{\"httpMethod\":\"GET\",\"payloadFormatVersion\":\"1.0\",\"type\":\"HTTP_PROXY\",\"uri\":\"https://ip-ranges.amazonaws.com/ip-ranges.json\"}}}}}",
},
},
{
Id: "bar",
Type: aws.AwsLoadBalancerResourceType,
Attrs: &resource.Attributes{},
},
{
Id: "alb-test",
Type: aws.AwsApplicationLoadBalancerResourceType,
Attrs: &resource.Attributes{},
},
},
expected: []*resource.Resource{
{
Id: "foo",
Type: aws.AwsApiGatewayRestApiResourceType,
Attrs: &resource.Attributes{
"body": "{\"info\":{\"title\":\"example\",\"version\":\"1.0\"},\"openapi\":\"3.0.1\",\"paths\":{\"/path1\":{\"get\":{\"parameters\":[{\"in\":\"query\",\"name\":\"type\",\"schema\":{\"type\":\"string\"}},{\"in\":\"query\",\"name\":\"page\",\"schema\":{\"type\":\"string\"}}],\"responses\":{\"200\":{\"content\":{\"application/json\":{\"schema\":{\"$ref\":\"#/components/schemas/Pets\"}}},\"description\":\"200 response\",\"headers\":{\"Access-Control-Allow-Origin\":{\"schema\":{\"type\":\"string\"}}}}},\"x-amazon-apigateway-integration\":{\"httpMethod\":\"GET\",\"payloadFormatVersion\":\"1.0\",\"type\":\"HTTP_PROXY\",\"uri\":\"https://ip-ranges.amazonaws.com/ip-ranges.json\",\"responses\":{\"2\\\\d{2}\":{\"responseTemplates\":{\"application/json\":\"#set ($root=$input.path('$')) { \\\"stage\\\": \\\"$root.name\\\", \\\"user-id\\\": \\\"$root.key\\\" }\",\"application/xml\":\"#set ($root=$input.path('$')) \\u003cstage\\u003e$root.name\\u003c/stage\\u003e \"},\"statusCode\":\"200\"}}}}},\"/path1/path2\":{\"get\":{\"x-amazon-apigateway-integration\":{\"httpMethod\":\"GET\",\"payloadFormatVersion\":\"1.0\",\"type\":\"HTTP_PROXY\",\"uri\":\"https://ip-ranges.amazonaws.com/ip-ranges.json\"}}}}}",
},
},
{
Id: "bar",
Type: aws.AwsLoadBalancerResourceType,
Attrs: &resource.Attributes{},
},
{
Id: "alb-test",
Type: aws.AwsLoadBalancerResourceType,
Attrs: &resource.Attributes{},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
factory := &terraform.MockResourceFactory{}
if tt.mocks != nil {
tt.mocks(factory)
}
m := NewAwsALBTransformer(factory)
err := m.Execute(&[]*resource.Resource{}, &tt.resourcesFromState)
if err != nil {
t.Fatal(err)
}
changelog, err := diff.Diff(tt.expected, tt.resourcesFromState)
if err != nil {
t.Fatal(err)
}
if len(changelog) > 0 {
for _, change := range changelog {
t.Errorf("%s got = %v, want %v", strings.Join(change.Path, "."), awsutil.Prettify(change.From), awsutil.Prettify(change.To))
}
}
})
}
}

View File

@ -38,6 +38,7 @@ func Init(version string, alerter *alerter.Alerter,
s3Repository := repository.NewS3Repository(client.NewAWSClientFactory(provider.session), repositoryCache)
ec2repository := repository.NewEC2Repository(provider.session, repositoryCache)
elbv2Repository := repository.NewELBV2Repository(provider.session, repositoryCache)
route53repository := repository.NewRoute53Repository(provider.session, repositoryCache)
lambdaRepository := repository.NewLambdaRepository(provider.session, repositoryCache)
rdsRepository := repository.NewRDSRepository(provider.session, repositoryCache)
@ -230,6 +231,8 @@ func Init(version string, alerter *alerter.Alerter,
remoteLibrary.AddEnumerator(NewLaunchConfigurationEnumerator(autoscalingRepository, factory))
remoteLibrary.AddEnumerator(NewLoadBalancerEnumerator(elbv2Repository, factory))
err = resourceSchemaRepository.Init(terraform.AWS, provider.Version(), provider.Schema())
if err != nil {
return err

View File

@ -0,0 +1,48 @@
package aws
import (
"github.com/snyk/driftctl/pkg/remote/aws/repository"
remoteerror "github.com/snyk/driftctl/pkg/remote/error"
"github.com/snyk/driftctl/pkg/resource"
"github.com/snyk/driftctl/pkg/resource/aws"
)
type LoadBalancerEnumerator struct {
repository repository.ELBV2Repository
factory resource.ResourceFactory
}
func NewLoadBalancerEnumerator(repo repository.ELBV2Repository, factory resource.ResourceFactory) *LoadBalancerEnumerator {
return &LoadBalancerEnumerator{
repository: repo,
factory: factory,
}
}
func (e *LoadBalancerEnumerator) SupportedType() resource.ResourceType {
return aws.AwsLoadBalancerResourceType
}
func (e *LoadBalancerEnumerator) Enumerate() ([]*resource.Resource, error) {
loadBalancers, err := e.repository.ListAllLoadBalancers()
if err != nil {
return nil, remoteerror.NewResourceListingError(err, string(e.SupportedType()))
}
results := make([]*resource.Resource, 0, len(loadBalancers))
for _, lb := range loadBalancers {
results = append(
results,
e.factory.CreateAbstractResource(
string(e.SupportedType()),
*lb.LoadBalancerArn,
map[string]interface{}{
"name": *lb.LoadBalancerName,
},
),
)
}
return results, err
}

View File

@ -0,0 +1,42 @@
package repository
import (
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/aws/aws-sdk-go/service/elbv2/elbv2iface"
"github.com/snyk/driftctl/pkg/remote/cache"
)
type ELBV2Repository interface {
ListAllLoadBalancers() ([]*elbv2.LoadBalancer, error)
}
type elbv2Repository struct {
client elbv2iface.ELBV2API
cache cache.Cache
}
func NewELBV2Repository(session *session.Session, c cache.Cache) *elbv2Repository {
return &elbv2Repository{
elbv2.New(session),
c,
}
}
func (r *elbv2Repository) ListAllLoadBalancers() ([]*elbv2.LoadBalancer, error) {
if v := r.cache.Get("elbListAllLoadBalancers"); v != nil {
return v.([]*elbv2.LoadBalancer), nil
}
results := make([]*elbv2.LoadBalancer, 0)
input := &elbv2.DescribeLoadBalancersInput{}
err := r.client.DescribeLoadBalancersPages(input, func(res *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool {
results = append(results, res.LoadBalancers...)
return !lastPage
})
if err != nil {
return nil, err
}
r.cache.Put("elbListAllLoadBalancers", results)
return results, err
}

View File

@ -0,0 +1,128 @@
package repository
import (
"strings"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/pkg/errors"
"github.com/snyk/driftctl/pkg/remote/cache"
awstest "github.com/snyk/driftctl/test/aws"
"github.com/stretchr/testify/mock"
"github.com/r3labs/diff/v2"
"github.com/stretchr/testify/assert"
)
func Test_ELBv2Repository_ListAllLoadBalancers(t *testing.T) {
dummyError := errors.New("dummy error")
tests := []struct {
name string
mocks func(*awstest.MockFakeELBV2, *cache.MockCache)
want []*elbv2.LoadBalancer
wantErr error
}{
{
name: "list load balancers",
mocks: func(client *awstest.MockFakeELBV2, store *cache.MockCache) {
results := &elbv2.DescribeLoadBalancersOutput{
LoadBalancers: []*elbv2.LoadBalancer{
{
LoadBalancerArn: aws.String("test-1"),
LoadBalancerName: aws.String("test-1"),
},
{
LoadBalancerArn: aws.String("test-2"),
LoadBalancerName: aws.String("test-2"),
},
},
}
store.On("Get", "elbListAllLoadBalancers").Return(nil).Once()
client.On("DescribeLoadBalancersPages",
&elbv2.DescribeLoadBalancersInput{},
mock.MatchedBy(func(callback func(res *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool) bool {
callback(&elbv2.DescribeLoadBalancersOutput{LoadBalancers: []*elbv2.LoadBalancer{
results.LoadBalancers[0],
}}, false)
callback(&elbv2.DescribeLoadBalancersOutput{LoadBalancers: []*elbv2.LoadBalancer{
results.LoadBalancers[1],
}}, true)
return true
})).Return(nil).Once()
store.On("Put", "elbListAllLoadBalancers", results.LoadBalancers).Return(false).Once()
},
want: []*elbv2.LoadBalancer{
{
LoadBalancerArn: aws.String("test-1"),
LoadBalancerName: aws.String("test-1"),
},
{
LoadBalancerArn: aws.String("test-2"),
LoadBalancerName: aws.String("test-2"),
},
},
},
{
name: "list load balancers from cache",
mocks: func(client *awstest.MockFakeELBV2, store *cache.MockCache) {
output := &elbv2.DescribeLoadBalancersOutput{
LoadBalancers: []*elbv2.LoadBalancer{
{
LoadBalancerArn: aws.String("test-1"),
LoadBalancerName: aws.String("test-1"),
},
},
}
store.On("Get", "elbListAllLoadBalancers").Return(output.LoadBalancers).Once()
},
want: []*elbv2.LoadBalancer{
{
LoadBalancerArn: aws.String("test-1"),
LoadBalancerName: aws.String("test-1"),
},
},
},
{
name: "error listing load balancers",
mocks: func(client *awstest.MockFakeELBV2, store *cache.MockCache) {
store.On("Get", "elbListAllLoadBalancers").Return(nil).Once()
client.On("DescribeLoadBalancersPages",
&elbv2.DescribeLoadBalancersInput{},
mock.MatchedBy(func(callback func(res *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool) bool {
callback(&elbv2.DescribeLoadBalancersOutput{LoadBalancers: []*elbv2.LoadBalancer{}}, true)
return true
})).Return(dummyError).Once()
},
wantErr: dummyError,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
store := &cache.MockCache{}
client := &awstest.MockFakeELBV2{}
tt.mocks(client, store)
r := &elbv2Repository{
client: client,
cache: store,
}
got, err := r.ListAllLoadBalancers()
assert.Equal(t, tt.wantErr, err)
changelog, err := diff.Diff(got, tt.want)
assert.Nil(t, err)
if len(changelog) > 0 {
for _, change := range changelog {
t.Errorf("%s: %v -> %v", strings.Join(change.Path, "."), change.From, change.To)
}
t.Fail()
}
})
}
}

View File

@ -0,0 +1,36 @@
// Code generated by mockery v2.10.0. DO NOT EDIT.
package repository
import (
elbv2 "github.com/aws/aws-sdk-go/service/elbv2"
mock "github.com/stretchr/testify/mock"
)
// MockELBV2Repository is an autogenerated mock type for the ELBV2Repository type
type MockELBV2Repository struct {
mock.Mock
}
// ListAllLoadBalancers provides a mock function with given fields:
func (_m *MockELBV2Repository) ListAllLoadBalancers() ([]*elbv2.LoadBalancer, error) {
ret := _m.Called()
var r0 []*elbv2.LoadBalancer
if rf, ok := ret.Get(0).(func() []*elbv2.LoadBalancer); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*elbv2.LoadBalancer)
}
}
var r1 error
if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
}

View File

@ -0,0 +1,105 @@
package remote
import (
"errors"
"testing"
awssdk "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/snyk/driftctl/mocks"
"github.com/snyk/driftctl/pkg/filter"
"github.com/snyk/driftctl/pkg/remote/alerts"
"github.com/snyk/driftctl/pkg/remote/aws"
"github.com/snyk/driftctl/pkg/remote/aws/repository"
"github.com/snyk/driftctl/pkg/remote/common"
remoteerr "github.com/snyk/driftctl/pkg/remote/error"
"github.com/snyk/driftctl/pkg/resource"
resourceaws "github.com/snyk/driftctl/pkg/resource/aws"
"github.com/snyk/driftctl/pkg/terraform"
testresource "github.com/snyk/driftctl/test/resource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestLoadBalancer(t *testing.T) {
tests := []struct {
test string
mocks func(*repository.MockELBV2Repository, *mocks.AlerterInterface)
assertExpected func(t *testing.T, got []*resource.Resource)
wantErr error
}{
{
test: "no load balancer",
mocks: func(repository *repository.MockELBV2Repository, alerter *mocks.AlerterInterface) {
repository.On("ListAllLoadBalancers").Return([]*elbv2.LoadBalancer{}, nil)
},
assertExpected: func(t *testing.T, got []*resource.Resource) {
assert.Len(t, got, 0)
},
},
{
test: "should list load balancers",
mocks: func(repository *repository.MockELBV2Repository, alerter *mocks.AlerterInterface) {
repository.On("ListAllLoadBalancers").Return([]*elbv2.LoadBalancer{
{
LoadBalancerArn: awssdk.String("arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/acc-test-lb-tf/9114c60e08560420"),
LoadBalancerName: awssdk.String("acc-test-lb-tf"),
},
}, nil)
},
assertExpected: func(t *testing.T, got []*resource.Resource) {
assert.Len(t, got, 1)
assert.Equal(t, "arn:aws:elasticloadbalancing:us-east-1:533948124879:loadbalancer/app/acc-test-lb-tf/9114c60e08560420", got[0].ResourceId())
assert.Equal(t, resourceaws.AwsLoadBalancerResourceType, got[0].ResourceType())
},
},
{
test: "cannot list load balancers",
mocks: func(repository *repository.MockELBV2Repository, alerter *mocks.AlerterInterface) {
awsError := awserr.NewRequestFailure(awserr.New("AccessDeniedException", "", errors.New("")), 403, "")
repository.On("ListAllLoadBalancers").Return(nil, awsError)
alerter.On("SendAlert", resourceaws.AwsLoadBalancerResourceType, alerts.NewRemoteAccessDeniedAlert(common.RemoteAWSTerraform, remoteerr.NewResourceListingErrorWithType(awsError, resourceaws.AwsLoadBalancerResourceType, resourceaws.AwsLoadBalancerResourceType), alerts.EnumerationPhase)).Return()
},
assertExpected: func(t *testing.T, got []*resource.Resource) {
assert.Len(t, got, 0)
},
},
}
schemaRepository := testresource.InitFakeSchemaRepository("aws", "3.19.0")
resourceaws.InitResourcesMetadata(schemaRepository)
factory := terraform.NewTerraformResourceFactory(schemaRepository)
for _, c := range tests {
t.Run(c.test, func(tt *testing.T) {
scanOptions := ScannerOptions{}
remoteLibrary := common.NewRemoteLibrary()
// Initialize mocks
alerter := &mocks.AlerterInterface{}
fakeRepo := &repository.MockELBV2Repository{}
c.mocks(fakeRepo, alerter)
var repo repository.ELBV2Repository = fakeRepo
remoteLibrary.AddEnumerator(aws.NewLoadBalancerEnumerator(repo, factory))
testFilter := &filter.MockFilter{}
testFilter.On("IsTypeIgnored", mock.Anything).Return(false)
s := NewScanner(remoteLibrary, alerter, scanOptions, testFilter)
got, err := s.Resources()
assert.Equal(tt, c.wantErr, err)
if err != nil {
return
}
c.assertExpected(tt, got)
alerter.AssertExpectations(tt)
fakeRepo.AssertExpectations(tt)
})
}
}

View File

@ -0,0 +1,5 @@
{
"Typ": "WyJvYmplY3QiLHsiYWNjZXNzX2xvZ3MiOlsibGlzdCIsWyJvYmplY3QiLHsiYnVja2V0Ijoic3RyaW5nIiwiZW5hYmxlZCI6ImJvb2wiLCJwcmVmaXgiOiJzdHJpbmcifV1dLCJhcm4iOiJzdHJpbmciLCJhcm5fc3VmZml4Ijoic3RyaW5nIiwiY3VzdG9tZXJfb3duZWRfaXB2NF9wb29sIjoic3RyaW5nIiwiZG5zX25hbWUiOiJzdHJpbmciLCJkcm9wX2ludmFsaWRfaGVhZGVyX2ZpZWxkcyI6ImJvb2wiLCJlbmFibGVfY3Jvc3Nfem9uZV9sb2FkX2JhbGFuY2luZyI6ImJvb2wiLCJlbmFibGVfZGVsZXRpb25fcHJvdGVjdGlvbiI6ImJvb2wiLCJlbmFibGVfaHR0cDIiOiJib29sIiwiaWQiOiJzdHJpbmciLCJpZGxlX3RpbWVvdXQiOiJudW1iZXIiLCJpbnRlcm5hbCI6ImJvb2wiLCJpcF9hZGRyZXNzX3R5cGUiOiJzdHJpbmciLCJsb2FkX2JhbGFuY2VyX3R5cGUiOiJzdHJpbmciLCJuYW1lIjoic3RyaW5nIiwibmFtZV9wcmVmaXgiOiJzdHJpbmciLCJzZWN1cml0eV9ncm91cHMiOlsic2V0Iiwic3RyaW5nIl0sInN1Ym5ldF9tYXBwaW5nIjpbInNldCIsWyJvYmplY3QiLHsiYWxsb2NhdGlvbl9pZCI6InN0cmluZyIsIm91dHBvc3RfaWQiOiJzdHJpbmciLCJwcml2YXRlX2lwdjRfYWRkcmVzcyI6InN0cmluZyIsInN1Ym5ldF9pZCI6InN0cmluZyJ9XV0sInN1Ym5ldHMiOlsic2V0Iiwic3RyaW5nIl0sInRhZ3MiOlsibWFwIiwic3RyaW5nIl0sInRpbWVvdXRzIjpbIm9iamVjdCIseyJjcmVhdGUiOiJzdHJpbmciLCJkZWxldGUiOiJzdHJpbmciLCJ1cGRhdGUiOiJzdHJpbmcifV0sInZwY19pZCI6InN0cmluZyIsInpvbmVfaWQiOiJzdHJpbmcifV0=",
"Val": "eyJhY2Nlc3NfbG9ncyI6W3siYnVja2V0IjoiIiwiZW5hYmxlZCI6ZmFsc2UsInByZWZpeCI6IiJ9XSwiYXJuIjoiYXJuOmF3czplbGFzdGljbG9hZGJhbGFuY2luZzp1cy1lYXN0LTE6NTMzOTQ4MTI0ODc5OmxvYWRiYWxhbmNlci9hcHAvdGVzdC1sYi10Zi8zNWJlNTdkNDY3ZmYyMmI5IiwiYXJuX3N1ZmZpeCI6ImFwcC90ZXN0LWxiLXRmLzM1YmU1N2Q0NjdmZjIyYjkiLCJjdXN0b21lcl9vd25lZF9pcHY0X3Bvb2wiOiIiLCJkbnNfbmFtZSI6InRlc3QtbGItdGYtMjc4MjQxNDYzLnVzLWVhc3QtMS5lbGIuYW1hem9uYXdzLmNvbSIsImRyb3BfaW52YWxpZF9oZWFkZXJfZmllbGRzIjpmYWxzZSwiZW5hYmxlX2Nyb3NzX3pvbmVfbG9hZF9iYWxhbmNpbmciOm51bGwsImVuYWJsZV9kZWxldGlvbl9wcm90ZWN0aW9uIjpmYWxzZSwiZW5hYmxlX2h0dHAyIjp0cnVlLCJpZCI6ImFybjphd3M6ZWxhc3RpY2xvYWRiYWxhbmNpbmc6dXMtZWFzdC0xOjUzMzk0ODEyNDg3OTpsb2FkYmFsYW5jZXIvYXBwL3Rlc3QtbGItdGYvMzViZTU3ZDQ2N2ZmMjJiOSIsImlkbGVfdGltZW91dCI6NjAsImludGVybmFsIjpmYWxzZSwiaXBfYWRkcmVzc190eXBlIjoiaXB2NCIsImxvYWRfYmFsYW5jZXJfdHlwZSI6ImFwcGxpY2F0aW9uIiwibmFtZSI6InRlc3QtbGItdGYiLCJuYW1lX3ByZWZpeCI6bnVsbCwic2VjdXJpdHlfZ3JvdXBzIjpbInNnLTA2ZmVjZmFhNzExZTY1YjZjIl0sInN1Ym5ldF9tYXBwaW5nIjpbeyJhbGxvY2F0aW9uX2lkIjoiIiwib3V0cG9zdF9pZCI6IiIsInByaXZhdGVfaXB2NF9hZGRyZXNzIjoiIiwic3VibmV0X2lkIjoic3VibmV0LTAwMzcxMzUxM2QzN2MwOTA1In0seyJhbGxvY2F0aW9uX2lkIjoiIiwib3V0cG9zdF9pZCI6IiIsInByaXZhdGVfaXB2NF9hZGRyZXNzIjoiIiwic3VibmV0X2lkIjoic3VibmV0LTA2MzE2MmYyMzA1M2ViZmRkIn1dLCJzdWJuZXRzIjpbInN1Ym5ldC0wMDM3MTM1MTNkMzdjMDkwNSIsInN1Ym5ldC0wNjMxNjJmMjMwNTNlYmZkZCJdLCJ0YWdzIjp7IkVudmlyb25tZW50IjoiZGV2In0sInRpbWVvdXRzIjp7ImNyZWF0ZSI6bnVsbCwiZGVsZXRlIjpudWxsLCJ1cGRhdGUiOm51bGx9LCJ2cGNfaWQiOiJ2cGMtMGFlMWYxMzhhMDk3NDllZjEiLCJ6b25lX2lkIjoiWjM1U1hET1RSUTdYN0sifQ==",
"Err": null
}

View File

@ -0,0 +1,27 @@
[
{
"access_logs": null,
"arn": null,
"arn_suffix": null,
"customer_owned_ipv4_pool": null,
"dns_name": null,
"drop_invalid_header_fields": null,
"enable_cross_zone_load_balancing": null,
"enable_deletion_protection": null,
"enable_http2": null,
"id": null,
"idle_timeout": null,
"internal": null,
"ip_address_type": null,
"load_balancer_type": null,
"name": "acc-test-lb-tf",
"name_prefix": null,
"security_groups": null,
"subnet_mapping": null,
"subnets": null,
"tags": null,
"timeouts": null,
"vpc_id": null,
"zone_id": null
}
]

View File

@ -0,0 +1,3 @@
package aws
const AwsApplicationLoadBalancerResourceType = "aws_alb"

View File

@ -0,0 +1,30 @@
package aws_test
import (
"testing"
"github.com/snyk/driftctl/test"
"github.com/snyk/driftctl/test/acceptance"
)
func TestAcc_Aws_ApplicationLoadBalancer(t *testing.T) {
acceptance.Run(t, acceptance.AccTestCase{
TerraformVersion: "0.15.5",
Paths: []string{"./testdata/acc/aws_alb"},
Args: []string{"scan"},
Checks: []acceptance.AccCheck{
{
Env: map[string]string{
"AWS_REGION": "us-east-1",
},
Check: func(result *test.ScanResult, stdout string, err error) {
if err != nil {
t.Fatal(err)
}
result.AssertInfrastructureIsInSync()
result.AssertManagedCount(1)
},
},
},
})
}

View File

@ -0,0 +1,13 @@
package aws
import "github.com/snyk/driftctl/pkg/resource"
const AwsLoadBalancerResourceType = "aws_lb"
func initAwsLoadBalancerMetaData(resourceSchemaRepository resource.SchemaRepositoryInterface) {
resourceSchemaRepository.SetHumanReadableAttributesFunc(AwsLoadBalancerResourceType, func(res *resource.Resource) map[string]string {
return map[string]string{
"Name": *res.Attributes().GetString("name"),
}
})
}

View File

@ -0,0 +1,30 @@
package aws_test
import (
"testing"
"github.com/snyk/driftctl/test"
"github.com/snyk/driftctl/test/acceptance"
)
func TestAcc_Aws_LoadBalancer(t *testing.T) {
acceptance.Run(t, acceptance.AccTestCase{
TerraformVersion: "0.15.5",
Paths: []string{"./testdata/acc/aws_lb"},
Args: []string{"scan"},
Checks: []acceptance.AccCheck{
{
Env: map[string]string{
"AWS_REGION": "us-east-1",
},
Check: func(result *test.ScanResult, stdout string, err error) {
if err != nil {
t.Fatal(err)
}
result.AssertInfrastructureIsInSync()
result.AssertManagedCount(1)
},
},
},
})
}

View File

@ -106,6 +106,8 @@ func TestAWS_Metadata_Flags(t *testing.T) {
AwsNetworkACLRuleResourceType: {resource.FlagDeepMode},
AwsLaunchTemplateResourceType: {resource.FlagDeepMode},
AwsLaunchConfigurationResourceType: {},
AwsLoadBalancerResourceType: {},
AwsApplicationLoadBalancerResourceType: {},
}
schemaRepository := testresource.InitFakeSchemaRepository(tf.AWS, "3.19.0")

View File

@ -66,4 +66,5 @@ func InitResourcesMetadata(resourceSchemaRepository resource.SchemaRepositoryInt
initAwsApiGatewayV2ModelMetaData(resourceSchemaRepository)
initAwsApiGatewayV2MappingMetaData(resourceSchemaRepository)
initAwsEbsEncryptionByDefaultMetaData(resourceSchemaRepository)
initAwsLoadBalancerMetaData(resourceSchemaRepository)
}

View File

@ -0,0 +1,2 @@
*
!aws_lb

View File

@ -0,0 +1,21 @@
# This file is maintained automatically by "terraform init".
# Manual edits may be lost in future updates.
provider "registry.terraform.io/hashicorp/aws" {
version = "4.8.0"
hashes = [
"h1:T9Typ5V+dDwecG9USCLbW4oayxN3cxEGsG+OJzzjRgY=",
"zh:16cbdbc03ad13358d12433e645e2ab5a615e3a3662a74e3c317267c9377713d8",
"zh:1d813c5e6c21fe370652495e29f783db4e65037f913ff0d53d28515c36fbb70a",
"zh:31ad8282e31d0fac62e96fc2321a68ad4b92ab90f560be5f875d1b01a493e491",
"zh:5099a9e699784cabb5686d2cb52ca910f9c697e977c654ecedd196e838387623",
"zh:5758cbb813091db8573f27bba37c48f63ba95f2104f3bc49f13131e3c305b848",
"zh:67ea77fb00bf0a09e712f5259a7acb494ce503a34809b7919996744fd92e3312",
"zh:72c87be5d1f7917d4281c14a3335a9ec3cd57bf63d95a440faa7035248083dcd",
"zh:79005154b9f5eccc1580e0eb803f0dfee68ba856703ef6489719cb014a3c2b18",
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
"zh:d27f9a8b5b30883a3e45f77506391524df0c66a76c3bc71f7236c3fc81d0597d",
"zh:e2985563dc652cf9b10420bc62f0a710308ef5c31e46b94c8ea10b8f27fa1ef3",
"zh:f11bb34ee0dad4bc865db51e7e299a4f030c5e9f6b6080d611797cc99deeb40a",
]
}

View File

@ -0,0 +1,54 @@
provider "aws" {
region = "us-east-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.100.0.0/16"
}
resource "aws_internet_gateway" "gw" {
vpc_id = aws_vpc.main.id
}
resource "aws_subnet" "main-1" {
vpc_id = aws_vpc.main.id
cidr_block = "10.100.0.0/24"
availability_zone = "us-east-1a"
}
resource "aws_subnet" "main-2" {
vpc_id = aws_vpc.main.id
cidr_block = "10.100.1.0/24"
availability_zone = "us-east-1b"
}
resource "aws_security_group" "lb_sg" {
name = "allow_tls_alb"
description = "Allow TLS inbound traffic"
vpc_id = aws_vpc.main.id
ingress {
description = "TLS from VPC"
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = [aws_vpc.main.cidr_block]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
resource "aws_alb" "test" {
name = "acc-test-alb-tf"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.lb_sg.id]
subnets = [aws_subnet.main-1.id,aws_subnet.main-2.id]
enable_deletion_protection = false
}

View File

@ -24,6 +24,10 @@ var supportedTypes = map[string]ResourceTypeMeta{
"aws_dynamodb_table": {},
"aws_ebs_snapshot": {},
"aws_ebs_volume": {},
"aws_alb": {children: []ResourceType{
"aws_lb",
}},
"aws_lb": {},
"aws_ebs_encryption_by_default": {},
"aws_ecr_repository": {},
"aws_eip": {children: []ResourceType{

9
test/aws/elbv2.go Normal file
View File

@ -0,0 +1,9 @@
package aws
import (
"github.com/aws/aws-sdk-go/service/elbv2/elbv2iface"
)
type FakeELBV2 interface {
elbv2iface.ELBV2API
}

2949
test/aws/mock_FakeELBV2.go Normal file

File diff suppressed because it is too large Load Diff