44 "fmt"
55 "os"
66 "os/signal"
7+ "path"
8+ "path/filepath"
79 "regexp"
810 "strings"
911 "syscall"
@@ -15,9 +17,12 @@ import (
1517 "github.com/sirupsen/logrus"
1618 "github.com/snyk/driftctl/build"
1719 "github.com/snyk/driftctl/pkg/analyser"
20+ "github.com/snyk/driftctl/pkg/iac/config"
21+ "github.com/snyk/driftctl/pkg/iac/terraform/state"
1822 "github.com/snyk/driftctl/pkg/memstore"
1923 "github.com/snyk/driftctl/pkg/remote/common"
2024 "github.com/snyk/driftctl/pkg/telemetry"
25+ "github.com/snyk/driftctl/pkg/terraform/hcl"
2126 "github.com/snyk/driftctl/pkg/terraform/lock"
2227 "github.com/spf13/cobra"
2328
@@ -146,7 +151,7 @@ func NewScanCmd(opts *pkg.ScanOptions) *cobra.Command {
146151 fl .StringSliceP (
147152 "from" ,
148153 "f" ,
149- []string {"tfstate://terraform.tfstate" },
154+ []string {},
150155 "IaC sources, by default try to find local terraform.tfstate file\n " +
151156 "Accepted schemes are: " + strings .Join (supplier .GetSupportedSchemes (), "," )+ "\n " ,
152157 )
@@ -259,6 +264,22 @@ func scanRun(opts *pkg.ScanOptions) error {
259264 globaloutput .ChangePrinter (globaloutput .NewConsolePrinter ())
260265 }
261266
267+ if len (opts .From ) == 0 {
268+ supplierConfigs , err := retrieveBackendsFromHCL ("" )
269+ if err != nil {
270+ return err
271+ }
272+ opts .From = append (opts .From , supplierConfigs ... )
273+ }
274+
275+ if len (opts .From ) == 0 {
276+ opts .From = append (opts .From , config.SupplierConfig {
277+ Key : state .TerraformStateReaderSupplier ,
278+ Backend : backend .BackendKeyFile ,
279+ Path : "terraform.tfstate" ,
280+ })
281+ }
282+
262283 providerLibrary := terraform .NewProviderLibrary ()
263284 remoteLibrary := common .NewRemoteLibrary ()
264285
@@ -360,3 +381,29 @@ func validateTfProviderVersionString(version string) error {
360381 }
361382 return nil
362383}
384+
385+ func retrieveBackendsFromHCL (workdir string ) ([]config.SupplierConfig , error ) {
386+ matches , err := filepath .Glob (path .Join (workdir , "*.tf" ))
387+ if err != nil {
388+ return nil , err
389+ }
390+ supplierConfigs := make ([]config.SupplierConfig , 0 )
391+
392+ for _ , match := range matches {
393+ body , err := hcl .ParseTerraformFromHCL (match )
394+ if err != nil {
395+ logrus .
396+ WithField ("file" , match ).
397+ WithField ("error" , err ).
398+ Debug ("Error parsing backend block in Terraform file" )
399+ continue
400+ }
401+
402+ if supplierConfig := body .Backend .SupplierConfig (); supplierConfig != nil {
403+ globaloutput .Printf (color .WhiteString ("Using Terraform state %s found in %s. Use the --from flag to specify another state file.\n " ), supplierConfig , match )
404+ supplierConfigs = append (supplierConfigs , * supplierConfig )
405+ }
406+ }
407+
408+ return supplierConfigs , nil
409+ }
0 commit comments