github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/test/docker_test.go (about) 1 package test 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path" 8 "path/filepath" 9 "strings" 10 "testing" 11 12 "github.com/liamg/memoryfs" 13 "github.com/open-policy-agent/opa/bundle" 14 15 "github.com/khulnasoft-lab/defsec/pkg/scanners/options" 16 17 "github.com/khulnasoft-lab/defsec/pkg/scan" 18 "github.com/khulnasoft-lab/defsec/pkg/scanners/dockerfile" 19 20 "github.com/stretchr/testify/assert" 21 "github.com/stretchr/testify/require" 22 ) 23 24 func Test_Docker_RegoPoliciesFromDisk(t *testing.T) { 25 t.Parallel() 26 27 entries, err := os.ReadDir("./testdata/dockerfile") 28 require.NoError(t, err) 29 30 policiesPath, err := filepath.Abs("../rules") 31 require.NoError(t, err) 32 scanner := dockerfile.NewScanner( 33 options.ScannerWithPolicyDirs(filepath.Base(policiesPath)), 34 ) 35 memfs := memoryfs.New() 36 // add policies 37 err = addFilesToMemFS(memfs, true, policiesPath) 38 require.NoError(t, err) 39 40 // add test data 41 testDataPath, err := filepath.Abs("./testdata/dockerfile") 42 require.NoError(t, err) 43 err = addFilesToMemFS(memfs, false, testDataPath) 44 require.NoError(t, err) 45 46 results, err := scanner.ScanFS(context.TODO(), memfs, filepath.Base(testDataPath)) 47 require.NoError(t, err) 48 49 for _, entry := range entries { 50 if !entry.IsDir() { 51 continue 52 } 53 t.Run(entry.Name(), func(t *testing.T) { 54 require.NoError(t, err) 55 t.Run(entry.Name(), func(t *testing.T) { 56 var matched int 57 for _, result := range results { 58 if result.Rule().HasID(entry.Name()) && result.Status() == scan.StatusFailed { 59 if result.Description() != "Specify at least 1 USER command in Dockerfile with non-root user as argument" { 60 assert.Greater(t, result.Range().GetStartLine(), 0) 61 assert.Greater(t, result.Range().GetEndLine(), 0) 62 } 63 if !strings.HasSuffix(result.Range().GetFilename(), entry.Name()) { 64 continue 65 } 66 matched++ 67 } 68 } 69 assert.Equal(t, 1, matched, "Rule should be matched once") 70 }) 71 72 }) 73 } 74 } 75 76 func Test_Docker_RegoPoliciesEmbedded(t *testing.T) { 77 t.Parallel() 78 79 entries, err := os.ReadDir("./testdata/dockerfile") 80 require.NoError(t, err) 81 82 scanner := dockerfile.NewScanner(options.ScannerWithEmbeddedPolicies(true), options.ScannerWithEmbeddedLibraries(true)) 83 srcFS := os.DirFS("../") 84 85 results, err := scanner.ScanFS(context.TODO(), srcFS, "test/testdata/dockerfile") 86 require.NoError(t, err) 87 88 for _, entry := range entries { 89 if !entry.IsDir() { 90 continue 91 } 92 t.Run(entry.Name(), func(t *testing.T) { 93 require.NoError(t, err) 94 t.Run(entry.Name(), func(t *testing.T) { 95 var matched bool 96 for _, result := range results { 97 if result.Rule().HasID(entry.Name()) && result.Status() == scan.StatusFailed { 98 if result.Description() != "Specify at least 1 USER command in Dockerfile with non-root user as argument" { 99 assert.Greater(t, result.Range().GetStartLine(), 0) 100 assert.Greater(t, result.Range().GetEndLine(), 0) 101 } 102 assert.Equal(t, fmt.Sprintf("test/testdata/dockerfile/%s/Dockerfile.denied", entry.Name()), result.Range().GetFilename()) 103 matched = true 104 } 105 } 106 assert.True(t, matched) 107 }) 108 109 }) 110 } 111 } 112 113 func addFilesToMemFS(memfs *memoryfs.FS, typePolicy bool, folderName string) error { 114 base := filepath.Base(folderName) 115 if err := memfs.MkdirAll(base, 0o700); err != nil { 116 return err 117 } 118 err := filepath.Walk(filepath.FromSlash(folderName), 119 func(fpath string, info os.FileInfo, err error) error { 120 if err != nil { 121 return err 122 } 123 if info.IsDir() { 124 return nil 125 } 126 if typePolicy && !isRegoFile(info.Name()) { 127 return nil 128 } 129 data, err := os.ReadFile(fpath) 130 if err != nil { 131 return err 132 } 133 fileName := getFileName(fpath, info, typePolicy) 134 if err := memfs.WriteFile(path.Join(base, fileName), data, 0o644); err != nil { 135 return err 136 } 137 return nil 138 }) 139 140 if err != nil { 141 return err 142 } 143 return nil 144 } 145 146 func getFileName(fpath string, info os.FileInfo, typePolicy bool) string { 147 pathParts := strings.Split(fpath, filepath.FromSlash("/")) 148 fileName := info.Name() 149 // append test data folder to input file name example Dockerfile.allowed_DS001 150 if len(pathParts) > 2 && !typePolicy { 151 fileName = fmt.Sprintf("%s_%s", fileName, pathParts[len(pathParts)-2]) 152 } 153 return fileName 154 } 155 156 func isRegoFile(name string) bool { 157 return strings.HasSuffix(name, bundle.RegoExt) && !strings.HasSuffix(name, "_test"+bundle.RegoExt) 158 }