github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/scanners/terraform/scanner_integration_test.go (about)

     1  package terraform
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"testing"
     8  
     9  	"github.com/aquasecurity/defsec/pkg/scanners/options"
    10  	"github.com/aquasecurity/trivy-iac/test/testutil"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func Test_ScanRemoteModule(t *testing.T) {
    16  	if testing.Short() {
    17  		t.Skip("skipping integration test in short mode")
    18  	}
    19  	fs := testutil.CreateFS(t, map[string]string{
    20  		"main.tf": `
    21  module "s3_bucket" {
    22    source = "terraform-aws-modules/s3-bucket/aws"
    23  
    24    bucket = "my-s3-bucket"
    25  }
    26  `,
    27  		"/rules/bucket_name.rego": `
    28  # METADATA
    29  # schemas:
    30  # - input: schema.input
    31  # custom:
    32  #   avd_id: AVD-AWS-0001
    33  #   input:
    34  #     selector:
    35  #     - type: cloud
    36  #       subtypes:
    37  #         - service: s3
    38  #           provider: aws
    39  package defsec.test.aws1
    40  deny[res] {
    41    bucket := input.aws.s3.buckets[_]
    42    bucket.name.value == ""
    43    res := result.new("The name of the bucket must not be empty", bucket)
    44  }`,
    45  	})
    46  
    47  	debugLog := bytes.NewBuffer([]byte{})
    48  
    49  	scanner := New(
    50  		options.ScannerWithDebug(debugLog),
    51  		options.ScannerWithPolicyFilesystem(fs),
    52  		options.ScannerWithPolicyDirs("rules"),
    53  		options.ScannerWithEmbeddedPolicies(false),
    54  		options.ScannerWithEmbeddedLibraries(false),
    55  		options.ScannerWithRegoOnly(true),
    56  		ScannerWithAllDirectories(true),
    57  		ScannerWithSkipCachedModules(true),
    58  	)
    59  
    60  	results, err := scanner.ScanFS(context.TODO(), fs, ".")
    61  	require.NoError(t, err)
    62  
    63  	assert.Len(t, results.GetPassed(), 1)
    64  
    65  	if t.Failed() {
    66  		fmt.Printf("Debug logs:\n%s\n", debugLog.String())
    67  	}
    68  }
    69  
    70  func Test_ScanChildUseRemoteModule(t *testing.T) {
    71  	if testing.Short() {
    72  		t.Skip("skipping integration test in short mode")
    73  	}
    74  	fs := testutil.CreateFS(t, map[string]string{
    75  		"main.tf": `
    76  module "this" {
    77  	source = "./modules/s3"
    78  	bucket = "my-s3-bucket"
    79  }
    80  `,
    81  		"modules/s3/main.tf": `
    82  variable "bucket" {
    83  	type = string
    84  }
    85  
    86  module "s3_bucket" {
    87    source = "github.com/terraform-aws-modules/terraform-aws-s3-bucket?ref=v3.15.1"
    88    bucket = var.bucket
    89  }
    90  `,
    91  		"rules/bucket_name.rego": `
    92  # METADATA
    93  # schemas:
    94  # - input: schema.input
    95  # custom:
    96  #   avd_id: AVD-AWS-0001
    97  #   input:
    98  #     selector:
    99  #     - type: cloud
   100  #       subtypes:
   101  #         - service: s3
   102  #           provider: aws
   103  package defsec.test.aws1
   104  deny[res] {
   105    bucket := input.aws.s3.buckets[_]
   106    bucket.name.value == ""
   107    res := result.new("The name of the bucket must not be empty", bucket)
   108  }`,
   109  	})
   110  
   111  	debugLog := bytes.NewBuffer([]byte{})
   112  
   113  	scanner := New(
   114  		options.ScannerWithDebug(debugLog),
   115  		options.ScannerWithPolicyFilesystem(fs),
   116  		options.ScannerWithPolicyDirs("rules"),
   117  		options.ScannerWithEmbeddedPolicies(false),
   118  		options.ScannerWithEmbeddedLibraries(false),
   119  		options.ScannerWithRegoOnly(true),
   120  		ScannerWithAllDirectories(true),
   121  		ScannerWithSkipCachedModules(true),
   122  	)
   123  
   124  	results, err := scanner.ScanFS(context.TODO(), fs, ".")
   125  	require.NoError(t, err)
   126  
   127  	assert.Len(t, results.GetPassed(), 1)
   128  
   129  	if t.Failed() {
   130  		fmt.Printf("Debug logs:\n%s\n", debugLog.String())
   131  	}
   132  }
   133  
   134  func Test_OptionWithSkipDownloaded(t *testing.T) {
   135  	if testing.Short() {
   136  		t.Skip("skipping integration test in short mode")
   137  	}
   138  
   139  	fs := testutil.CreateFS(t, map[string]string{
   140  		"test/main.tf": `
   141  module "s3-bucket" {
   142    source   = "terraform-aws-modules/s3-bucket/aws"
   143    version = "3.14.0"
   144    bucket = "mybucket"
   145    create_bucket = true
   146  }
   147  `,
   148  		// creating our own rule for the reliability of the test
   149  		"/rules/test.rego": `
   150  package defsec.abcdefg
   151  
   152  __rego_input__ := {
   153  	"combine": false,
   154  	"selector": [{"type": "defsec", "subtypes": [{"service": "s3", "provider": "aws"}]}],
   155  }
   156  
   157  deny[cause] {
   158  	bucket := input.aws.s3.buckets[_]
   159  	bucket.name.value == "mybucket"
   160  	cause := bucket.name
   161  }`,
   162  	})
   163  
   164  	t.Run("without skip", func(t *testing.T) {
   165  		scanner := New(
   166  			options.ScannerWithPolicyDirs("rules"),
   167  			options.ScannerWithRegoOnly(true),
   168  			options.ScannerWithEmbeddedPolicies(false),
   169  			options.ScannerWithEmbeddedLibraries(true),
   170  		)
   171  		results, err := scanner.ScanFS(context.TODO(), fs, "test")
   172  		require.NoError(t, err)
   173  
   174  		assert.Len(t, results, 1)
   175  		assert.Len(t, results.GetFailed(), 1)
   176  	})
   177  
   178  	t.Run("with skip", func(t *testing.T) {
   179  		scanner := New(
   180  			ScannerWithSkipDownloaded(true),
   181  			options.ScannerWithPolicyDirs("rules"),
   182  			options.ScannerWithRegoOnly(true),
   183  			options.ScannerWithEmbeddedPolicies(false),
   184  			options.ScannerWithEmbeddedLibraries(true),
   185  		)
   186  		results, err := scanner.ScanFS(context.TODO(), fs, "test")
   187  		require.NoError(t, err)
   188  
   189  		assert.Len(t, results, 1)
   190  		assert.Len(t, results.GetIgnored(), 1)
   191  	})
   192  }
   193  
   194  func Test_OptionWithSkipDownloadedIAMDocument(t *testing.T) {
   195  	if testing.Short() {
   196  		t.Skip("skipping integration test in short mode")
   197  	}
   198  
   199  	fs := testutil.CreateFS(t, map[string]string{
   200  		"test/main.tf": `
   201  module "karpenter" {
   202    source  = "terraform-aws-modules/eks/aws//modules/karpenter"
   203    version = "19.21.0"
   204  
   205    cluster_name           = "test"
   206    irsa_oidc_provider_arn = "example"
   207  }
   208  `,
   209  		// creating our own rule for the reliability of the test
   210  		"/rules/test.rego": `
   211  package defsec.abcdefg
   212  
   213  __rego_input__ := {
   214  	"combine": false,
   215  	"selector": [{"type": "defsec", "subtypes": [{"service": "iam", "provider": "aws"}]}],
   216  }
   217  
   218  allows_permission(statements, permission, effect) {
   219  	statement := statements[_]
   220  	statement.Effect == effect
   221  	action = statement.Action[_]
   222  	action == permission
   223  }
   224  
   225  deny[res] {
   226  	policy := input.aws.iam.policies[_]
   227  	value = json.unmarshal(policy.document.value)
   228  	statements = value.Statement
   229  	not allows_permission(statements, "iam:PassRole", "Deny")
   230  	allows_permission(statements, "iam:PassRole", "Allow")
   231  	res = result.new("IAM policy allows 'iam:PassRole' action", policy.document)
   232  }
   233  `,
   234  	})
   235  
   236  	scanner := New(
   237  		ScannerWithSkipDownloaded(true),
   238  		options.ScannerWithPolicyDirs("rules"),
   239  		options.ScannerWithRegoOnly(true),
   240  		options.ScannerWithEmbeddedLibraries(true),
   241  		options.ScannerWithEmbeddedPolicies(false),
   242  	)
   243  	results, err := scanner.ScanFS(context.TODO(), fs, "test")
   244  	require.NoError(t, err)
   245  	assert.Len(t, results, 1)
   246  
   247  	ignored := results.GetIgnored()
   248  	assert.Len(t, ignored, 1)
   249  	assert.NotNil(t, ignored[0].Metadata().Parent())
   250  }