2020-12-09 15:31:34 +00:00
|
|
|
package pkg
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
|
2021-03-29 16:10:50 +00:00
|
|
|
"github.com/jmespath/go-jmespath"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
|
2020-12-16 12:02:02 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/alerter"
|
2020-12-09 15:31:34 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/analyser"
|
2021-04-09 11:15:16 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/cmd/scan/output"
|
2020-12-09 15:31:34 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/filter"
|
2021-04-09 11:15:16 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/iac/config"
|
|
|
|
"github.com/cloudskiff/driftctl/pkg/iac/terraform/state/backend"
|
2020-12-09 15:31:34 +00:00
|
|
|
"github.com/cloudskiff/driftctl/pkg/middlewares"
|
|
|
|
"github.com/cloudskiff/driftctl/pkg/resource"
|
|
|
|
)
|
|
|
|
|
2021-04-09 11:15:16 +00:00
|
|
|
type ScanOptions struct {
|
|
|
|
Coverage bool
|
|
|
|
Detect bool
|
|
|
|
From []config.SupplierConfig
|
|
|
|
To string
|
|
|
|
Output output.OutputConfig
|
|
|
|
Filter *jmespath.JMESPath
|
|
|
|
Quiet bool
|
|
|
|
BackendOptions *backend.Options
|
|
|
|
StrictMode bool
|
|
|
|
}
|
|
|
|
|
2020-12-09 15:31:34 +00:00
|
|
|
type DriftCTL struct {
|
2021-03-29 16:10:50 +00:00
|
|
|
remoteSupplier resource.Supplier
|
|
|
|
iacSupplier resource.Supplier
|
|
|
|
alerter alerter.AlerterInterface
|
|
|
|
analyzer analyser.Analyzer
|
|
|
|
filter *jmespath.JMESPath
|
|
|
|
resourceFactory resource.ResourceFactory
|
2021-03-29 17:01:35 +00:00
|
|
|
strictMode bool
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-04-09 11:15:16 +00:00
|
|
|
func NewDriftCTL(remoteSupplier resource.Supplier, iacSupplier resource.Supplier, alerter *alerter.Alerter, resFactory resource.ResourceFactory, opts *ScanOptions) *DriftCTL {
|
|
|
|
return &DriftCTL{
|
|
|
|
remoteSupplier,
|
|
|
|
iacSupplier,
|
|
|
|
alerter,
|
|
|
|
analyser.NewAnalyzer(alerter),
|
|
|
|
opts.Filter,
|
|
|
|
resFactory,
|
|
|
|
opts.StrictMode,
|
|
|
|
}
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-02-09 18:44:27 +00:00
|
|
|
func (d DriftCTL) Run() (*analyser.Analysis, error) {
|
2020-12-09 15:31:34 +00:00
|
|
|
remoteResources, resourcesFromState, err := d.scan()
|
|
|
|
if err != nil {
|
2021-03-12 15:47:05 +00:00
|
|
|
return nil, errors.WithStack(err)
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
middleware := middlewares.NewChain(
|
|
|
|
middlewares.NewRoute53DefaultZoneRecordSanitizer(),
|
|
|
|
middlewares.NewS3BucketAcl(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewAwsInstanceBlockDeviceResourceMapper(d.resourceFactory),
|
2020-12-09 15:31:34 +00:00
|
|
|
middlewares.NewVPCDefaultSecurityGroupSanitizer(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewVPCSecurityGroupRuleSanitizer(d.resourceFactory),
|
2020-12-09 15:31:34 +00:00
|
|
|
middlewares.NewIamPolicyAttachmentSanitizer(),
|
2020-12-14 11:18:14 +00:00
|
|
|
middlewares.AwsInstanceEIP{},
|
2021-01-22 10:32:56 +00:00
|
|
|
middlewares.NewAwsDefaultInternetGatewayRoute(),
|
2021-01-20 21:54:41 +00:00
|
|
|
middlewares.NewAwsDefaultInternetGateway(),
|
2020-12-15 10:07:03 +00:00
|
|
|
middlewares.NewAwsDefaultVPC(),
|
2021-01-07 16:53:17 +00:00
|
|
|
middlewares.NewAwsDefaultSubnet(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewAwsRouteTableExpander(d.alerter, d.resourceFactory),
|
2021-01-14 17:11:02 +00:00
|
|
|
middlewares.NewAwsDefaultRouteTable(),
|
|
|
|
middlewares.NewAwsDefaultRoute(),
|
2021-01-20 16:28:56 +00:00
|
|
|
middlewares.NewAwsNatGatewayEipAssoc(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewAwsBucketPolicyExpander(d.resourceFactory),
|
|
|
|
middlewares.NewAwsSqsQueuePolicyExpander(d.resourceFactory),
|
2021-01-29 11:35:11 +00:00
|
|
|
middlewares.NewAwsDefaultSqsQueuePolicy(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewAwsSNSTopicPolicyExpander(d.resourceFactory),
|
2020-12-09 15:31:34 +00:00
|
|
|
)
|
|
|
|
|
2021-03-29 17:01:35 +00:00
|
|
|
if !d.strictMode {
|
|
|
|
middleware = append(middleware,
|
2021-04-01 17:30:02 +00:00
|
|
|
middlewares.NewAwsDefaults(),
|
2021-03-29 17:01:35 +00:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-12-09 15:31:34 +00:00
|
|
|
logrus.Debug("Ready to run middlewares")
|
|
|
|
err = middleware.Execute(&remoteResources, &resourcesFromState)
|
|
|
|
if err != nil {
|
2021-02-09 18:44:27 +00:00
|
|
|
return nil, errors.Wrap(err, "Unable to run middlewares")
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if d.filter != nil {
|
|
|
|
engine := filter.NewFilterEngine(d.filter)
|
|
|
|
remoteResources, err = engine.Run(remoteResources)
|
|
|
|
if err != nil {
|
2021-02-09 18:44:27 +00:00
|
|
|
return nil, errors.Wrap(err, "Unable to filter remote resources")
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
resourcesFromState, err = engine.Run(resourcesFromState)
|
|
|
|
if err != nil {
|
2021-02-09 18:44:27 +00:00
|
|
|
return nil, errors.Wrap(err, "Unable to filter state resources")
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
logrus.Debug("Checking for driftignore")
|
|
|
|
driftIgnore := filter.NewDriftIgnore()
|
|
|
|
|
2020-12-18 14:28:46 +00:00
|
|
|
analysis, err := d.analyzer.Analyze(remoteResources, resourcesFromState, driftIgnore)
|
2020-12-16 12:02:02 +00:00
|
|
|
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
2021-02-09 18:44:27 +00:00
|
|
|
return nil, errors.Wrap(err, "Unable to perform resources analysis")
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-02-09 18:44:27 +00:00
|
|
|
return &analysis, nil
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d DriftCTL) Stop() {
|
|
|
|
stoppableSupplier, ok := d.remoteSupplier.(resource.StoppableSupplier)
|
|
|
|
if ok {
|
|
|
|
logrus.WithFields(logrus.Fields{
|
|
|
|
"supplier": fmt.Sprintf("%T", d.remoteSupplier),
|
|
|
|
}).Debug("Stopping remote supplier")
|
|
|
|
stoppableSupplier.Stop()
|
|
|
|
}
|
|
|
|
|
|
|
|
stoppableSupplier, ok = d.iacSupplier.(resource.StoppableSupplier)
|
|
|
|
if ok {
|
|
|
|
stoppableSupplier.Stop()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d DriftCTL) scan() (remoteResources []resource.Resource, resourcesFromState []resource.Resource, err error) {
|
2021-01-15 11:44:13 +00:00
|
|
|
logrus.Info("Start reading IaC")
|
2021-01-08 11:10:25 +00:00
|
|
|
resourcesFromState, err = d.iacSupplier.Resources()
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2021-01-08 11:10:25 +00:00
|
|
|
logrus.Info("Start scanning cloud provider")
|
|
|
|
remoteResources, err = d.remoteSupplier.Resources()
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return remoteResources, resourcesFromState, err
|
|
|
|
}
|