2020-12-09 15:31:34 +00:00
|
|
|
package pkg
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2021-04-28 10:42:06 +00:00
|
|
|
"time"
|
2020-12-09 15:31:34 +00:00
|
|
|
|
2022-06-28 07:23:29 +00:00
|
|
|
"github.com/snyk/driftctl/enumeration/alerter"
|
|
|
|
resource2 "github.com/snyk/driftctl/pkg/resource"
|
|
|
|
|
2021-03-29 16:10:50 +00:00
|
|
|
"github.com/jmespath/go-jmespath"
|
|
|
|
"github.com/sirupsen/logrus"
|
2021-12-06 13:29:39 +00:00
|
|
|
"github.com/snyk/driftctl/pkg/memstore"
|
|
|
|
globaloutput "github.com/snyk/driftctl/pkg/output"
|
2021-03-29 16:10:50 +00:00
|
|
|
|
2022-06-28 07:23:29 +00:00
|
|
|
"github.com/snyk/driftctl/enumeration/resource"
|
2021-12-06 13:29:39 +00:00
|
|
|
"github.com/snyk/driftctl/pkg/analyser"
|
|
|
|
"github.com/snyk/driftctl/pkg/cmd/scan/output"
|
|
|
|
"github.com/snyk/driftctl/pkg/filter"
|
|
|
|
"github.com/snyk/driftctl/pkg/iac/config"
|
|
|
|
"github.com/snyk/driftctl/pkg/iac/terraform/state/backend"
|
|
|
|
"github.com/snyk/driftctl/pkg/middlewares"
|
2020-12-09 15:31:34 +00:00
|
|
|
)
|
|
|
|
|
2022-03-04 09:20:24 +00:00
|
|
|
type FmtOptions struct {
|
|
|
|
Output output.OutputConfig
|
|
|
|
}
|
|
|
|
|
2021-04-09 11:15:16 +00:00
|
|
|
type ScanOptions struct {
|
2021-04-27 16:32:03 +00:00
|
|
|
Coverage bool
|
|
|
|
Detect bool
|
|
|
|
From []config.SupplierConfig
|
|
|
|
To string
|
2021-07-21 15:57:05 +00:00
|
|
|
Output []output.OutputConfig
|
2021-04-27 16:32:03 +00:00
|
|
|
Filter *jmespath.JMESPath
|
|
|
|
Quiet bool
|
|
|
|
BackendOptions *backend.Options
|
|
|
|
StrictMode bool
|
|
|
|
DisableTelemetry bool
|
2021-06-03 09:43:15 +00:00
|
|
|
ProviderVersion string
|
2021-06-12 14:17:23 +00:00
|
|
|
ConfigDir string
|
2021-06-17 13:39:31 +00:00
|
|
|
DriftignorePath string
|
2022-02-14 10:58:12 +00:00
|
|
|
Driftignores []string
|
2021-06-11 15:10:06 +00:00
|
|
|
Deep bool
|
2022-02-24 17:33:09 +00:00
|
|
|
OnlyManaged bool
|
|
|
|
OnlyUnmanaged bool
|
2021-04-09 11:15:16 +00:00
|
|
|
}
|
|
|
|
|
2020-12-09 15:31:34 +00:00
|
|
|
type DriftCTL struct {
|
2021-12-22 09:34:14 +00:00
|
|
|
remoteSupplier resource.Supplier
|
2022-06-28 07:23:29 +00:00
|
|
|
iacSupplier resource2.IaCSupplier
|
2021-04-29 10:32:02 +00:00
|
|
|
alerter alerter.AlerterInterface
|
2021-07-26 09:17:32 +00:00
|
|
|
analyzer *analyser.Analyzer
|
2021-04-29 10:32:02 +00:00
|
|
|
resourceFactory resource.ResourceFactory
|
2021-05-03 16:41:52 +00:00
|
|
|
scanProgress globaloutput.Progress
|
|
|
|
iacProgress globaloutput.Progress
|
2021-04-29 10:32:02 +00:00
|
|
|
resourceSchemaRepository resource.SchemaRepositoryInterface
|
2021-06-17 13:39:31 +00:00
|
|
|
opts *ScanOptions
|
2021-06-28 12:39:14 +00:00
|
|
|
store memstore.Store
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-12-22 09:34:14 +00:00
|
|
|
func NewDriftCTL(remoteSupplier resource.Supplier,
|
2022-06-28 07:23:29 +00:00
|
|
|
iacSupplier resource2.IaCSupplier,
|
2021-04-30 17:19:26 +00:00
|
|
|
alerter *alerter.Alerter,
|
2021-07-26 09:17:32 +00:00
|
|
|
analyzer *analyser.Analyzer,
|
2021-04-30 17:19:26 +00:00
|
|
|
resFactory resource.ResourceFactory,
|
|
|
|
opts *ScanOptions,
|
|
|
|
scanProgress globaloutput.Progress,
|
|
|
|
iacProgress globaloutput.Progress,
|
2021-06-25 15:14:50 +00:00
|
|
|
resourceSchemaRepository resource.SchemaRepositoryInterface,
|
|
|
|
store memstore.Store) *DriftCTL {
|
2021-04-09 11:15:16 +00:00
|
|
|
return &DriftCTL{
|
|
|
|
remoteSupplier,
|
|
|
|
iacSupplier,
|
|
|
|
alerter,
|
2021-07-26 09:17:32 +00:00
|
|
|
analyzer,
|
2021-04-09 11:15:16 +00:00
|
|
|
resFactory,
|
2021-05-03 16:41:52 +00:00
|
|
|
scanProgress,
|
|
|
|
iacProgress,
|
2021-04-29 10:32:02 +00:00
|
|
|
resourceSchemaRepository,
|
2021-06-17 13:39:31 +00:00
|
|
|
opts,
|
2021-06-25 15:14:50 +00:00
|
|
|
store,
|
2021-04-09 11:15:16 +00:00
|
|
|
}
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-02-09 18:44:27 +00:00
|
|
|
func (d DriftCTL) Run() (*analyser.Analysis, error) {
|
2021-04-28 10:42:06 +00:00
|
|
|
start := time.Now()
|
2021-12-22 09:34:14 +00:00
|
|
|
remoteResources, resourcesFromState, err := d.scan()
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
2021-04-19 11:06:33 +00:00
|
|
|
return nil, err
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
middleware := middlewares.NewChain(
|
2021-05-17 15:03:10 +00:00
|
|
|
middlewares.NewRoute53RecordIDReconcilier(),
|
2020-12-09 15:31:34 +00:00
|
|
|
middlewares.NewRoute53DefaultZoneRecordSanitizer(),
|
|
|
|
middlewares.NewS3BucketAcl(),
|
2021-04-29 15:17:55 +00:00
|
|
|
middlewares.NewAwsInstanceBlockDeviceResourceMapper(d.resourceFactory),
|
2021-06-28 09:16:10 +00:00
|
|
|
middlewares.NewAwsDefaultSecurityGroupRule(),
|
2020-12-09 15:31:34 +00:00
|
|
|
middlewares.NewVPCDefaultSecurityGroupSanitizer(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewVPCSecurityGroupRuleSanitizer(d.resourceFactory),
|
2021-05-21 14:09:45 +00:00
|
|
|
middlewares.NewIamPolicyAttachmentTransformer(d.resourceFactory),
|
2021-05-12 09:35:41 +00:00
|
|
|
middlewares.NewIamPolicyAttachmentExpander(d.resourceFactory),
|
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-09-24 14:04:20 +00:00
|
|
|
middlewares.NewAwsDefaultNetworkACL(),
|
|
|
|
middlewares.NewAwsDefaultNetworkACLRule(),
|
|
|
|
middlewares.NewAwsNetworkACLExpander(d.resourceFactory),
|
2021-01-20 16:28:56 +00:00
|
|
|
middlewares.NewAwsNatGatewayEipAssoc(),
|
2021-03-29 16:10:50 +00:00
|
|
|
middlewares.NewAwsBucketPolicyExpander(d.resourceFactory),
|
2021-07-08 14:13:51 +00:00
|
|
|
middlewares.NewAwsSQSQueuePolicyExpander(d.resourceFactory, d.resourceSchemaRepository),
|
|
|
|
middlewares.NewAwsDefaultSQSQueuePolicy(),
|
2021-05-03 17:15:14 +00:00
|
|
|
middlewares.NewAwsSNSTopicPolicyExpander(d.resourceFactory, d.resourceSchemaRepository),
|
2021-06-17 15:25:53 +00:00
|
|
|
middlewares.NewAwsRoleManagedPolicyExpander(d.resourceFactory),
|
2021-06-22 14:33:12 +00:00
|
|
|
middlewares.NewTagsAllManager(),
|
2021-06-29 09:59:16 +00:00
|
|
|
middlewares.NewEipAssociationExpander(d.resourceFactory),
|
2021-09-03 14:22:43 +00:00
|
|
|
middlewares.NewRDSClusterInstanceExpander(d.resourceFactory),
|
2021-10-15 14:18:06 +00:00
|
|
|
middlewares.NewAwsApiGatewayDeploymentExpander(d.resourceFactory),
|
|
|
|
middlewares.NewAwsApiGatewayResourceExpander(d.resourceFactory),
|
2022-01-14 11:23:48 +00:00
|
|
|
middlewares.NewAwsApiGatewayApiExpander(d.resourceFactory),
|
2021-10-15 14:18:06 +00:00
|
|
|
middlewares.NewAwsApiGatewayRestApiPolicyExpander(d.resourceFactory),
|
2021-10-21 15:58:09 +00:00
|
|
|
middlewares.NewAwsConsoleApiGatewayGatewayResponse(),
|
2022-01-13 16:07:11 +00:00
|
|
|
middlewares.NewAwsApiGatewayDomainNamesReconciler(),
|
2022-04-14 14:39:41 +00:00
|
|
|
middlewares.NewAwsApiGatewayBasePathMappingReconciler(),
|
2022-03-28 13:07:02 +00:00
|
|
|
middlewares.NewAwsEbsEncryptionByDefaultReconciler(d.resourceFactory),
|
2022-04-07 07:56:02 +00:00
|
|
|
middlewares.NewAwsALBTransformer(d.resourceFactory),
|
2022-04-13 10:59:39 +00:00
|
|
|
middlewares.NewAwsALBListenerTransformer(d.resourceFactory),
|
2021-10-04 17:03:44 +00:00
|
|
|
|
2021-10-01 09:02:46 +00:00
|
|
|
middlewares.NewGoogleIAMBindingTransformer(d.resourceFactory),
|
|
|
|
middlewares.NewGoogleIAMPolicyTransformer(d.resourceFactory),
|
2022-03-28 13:20:17 +00:00
|
|
|
middlewares.NewGoogleComputeInstanceGroupManagerReconciler(),
|
2021-10-04 17:03:44 +00:00
|
|
|
|
2021-10-04 13:26:21 +00:00
|
|
|
middlewares.NewAzurermRouteExpander(d.resourceFactory),
|
2021-10-01 08:28:16 +00:00
|
|
|
middlewares.NewAzurermSubnetExpander(d.resourceFactory),
|
2022-03-31 14:09:41 +00:00
|
|
|
middlewares.NewAwsS3BucketPublicAccessBlockReconciler(),
|
2020-12-09 15:31:34 +00:00
|
|
|
)
|
|
|
|
|
2021-06-17 13:39:31 +00:00
|
|
|
if !d.opts.StrictMode {
|
2021-03-29 17:01:35 +00:00
|
|
|
middleware = append(middleware,
|
2021-04-01 17:30:02 +00:00
|
|
|
middlewares.NewAwsDefaults(),
|
2021-10-13 12:24:04 +00:00
|
|
|
middlewares.NewGoogleLegacyBucketIAMMember(),
|
|
|
|
middlewares.NewGoogleDefaultIAMMember(),
|
2022-01-24 12:00:00 +00:00
|
|
|
middlewares.NewAwsDefaultApiGatewayAccount(),
|
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-04-19 11:06:33 +00:00
|
|
|
return nil, err
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2021-06-17 13:39:31 +00:00
|
|
|
if d.opts.Filter != nil {
|
|
|
|
engine := filter.NewFilterEngine(d.opts.Filter)
|
2020-12-09 15:31:34 +00:00
|
|
|
remoteResources, err = engine.Run(remoteResources)
|
|
|
|
if err != nil {
|
2021-04-19 11:06:33 +00:00
|
|
|
return nil, err
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
resourcesFromState, err = engine.Run(resourcesFromState)
|
|
|
|
if err != nil {
|
2021-04-19 11:06:33 +00:00
|
|
|
return nil, err
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-22 09:34:14 +00:00
|
|
|
analysis, err := d.analyzer.Analyze(remoteResources, resourcesFromState)
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
2021-04-19 11:06:33 +00:00
|
|
|
return nil, err
|
2020-12-09 15:31:34 +00:00
|
|
|
}
|
|
|
|
|
2022-03-04 10:43:16 +00:00
|
|
|
analysis.SetIaCSourceCount(d.iacSupplier.SourceCount())
|
2021-06-10 13:25:54 +00:00
|
|
|
analysis.Duration = time.Since(start)
|
|
|
|
analysis.Date = time.Now()
|
|
|
|
|
2021-06-28 12:39:14 +00:00
|
|
|
d.store.Bucket(memstore.TelemetryBucket).Set("total_resources", analysis.Summary().TotalResources)
|
|
|
|
d.store.Bucket(memstore.TelemetryBucket).Set("total_managed", analysis.Summary().TotalManaged)
|
|
|
|
d.store.Bucket(memstore.TelemetryBucket).Set("duration", uint(analysis.Duration.Seconds()+0.5))
|
2022-03-04 10:43:16 +00:00
|
|
|
d.store.Bucket(memstore.TelemetryBucket).Set("iac_source_count", d.iacSupplier.SourceCount())
|
2021-06-25 15:14:50 +00:00
|
|
|
|
2021-12-22 09:34:14 +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()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-22 09:34:14 +00:00
|
|
|
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-05-03 16:41:52 +00:00
|
|
|
d.iacProgress.Start()
|
2021-01-08 11:10:25 +00:00
|
|
|
resourcesFromState, err = d.iacSupplier.Resources()
|
2021-05-04 13:24:42 +00:00
|
|
|
d.iacProgress.Stop()
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
2021-12-22 09:34:14 +00:00
|
|
|
logrus.Info("Start scanning cloud provider")
|
2021-05-03 16:41:52 +00:00
|
|
|
d.scanProgress.Start()
|
|
|
|
defer d.scanProgress.Stop()
|
2021-12-22 09:34:14 +00:00
|
|
|
remoteResources, err = d.remoteSupplier.Resources()
|
2020-12-09 15:31:34 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return remoteResources, resourcesFromState, err
|
|
|
|
}
|