github.com/aquasecurity/trivy-iac@v0.8.1-0.20240127024015-3d8e412cf0ab/pkg/detection/detect_test.go (about) 1 package detection 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "strings" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 ) 13 14 func Test_Detection(t *testing.T) { 15 tests := []struct { 16 name string 17 path string 18 r io.ReadSeeker 19 expected []FileType 20 }{ 21 { 22 name: "text file, no reader", 23 path: "something.txt", 24 expected: nil, 25 }, 26 { 27 name: "text file, with reader", 28 path: "something.txt", 29 r: strings.NewReader("some file content"), 30 expected: nil, 31 }, 32 { 33 name: "terraform, no reader", 34 path: "main.tf", 35 expected: []FileType{ 36 FileTypeTerraform, 37 }, 38 }, 39 { 40 name: "terraform, with reader", 41 path: "main.tf", 42 r: strings.NewReader("some file content"), 43 expected: []FileType{ 44 FileTypeTerraform, 45 }, 46 }, 47 { 48 name: "terraform json, no reader", 49 path: "main.tf.json", 50 expected: []FileType{ 51 FileTypeTerraform, 52 FileTypeJSON, 53 }, 54 }, 55 { 56 name: "terraform json, with reader", 57 path: "main.tf.json", 58 r: strings.NewReader(` 59 { 60 "variable": { 61 "example": { 62 "default": "hello" 63 } 64 } 65 } 66 `), 67 expected: []FileType{ 68 FileTypeTerraform, 69 FileTypeJSON, 70 }, 71 }, 72 { 73 name: "terraform vars, no reader", 74 path: "main.tfvars", 75 expected: []FileType{ 76 FileTypeTerraform, 77 }, 78 }, 79 { 80 name: "terraform vars, with reader", 81 path: "main.tfvars", 82 r: strings.NewReader("some_var = \"some value\""), 83 expected: []FileType{ 84 FileTypeTerraform, 85 }, 86 }, 87 { 88 name: "cloudformation, no reader", 89 path: "main.yaml", 90 expected: []FileType{ 91 FileTypeYAML, 92 FileTypeHelm, 93 }, 94 }, 95 { 96 name: "terraform plan, with reader", 97 path: "plan.json", 98 r: strings.NewReader(`{ 99 "format_version": "0.2", 100 "terraform_version": "1.0.3", 101 "variables": { 102 "bucket_name": { 103 "value": "tfsec-plan-testing" 104 } 105 }, 106 "planned_values": {}, 107 "resource_changes": [], 108 "prior_state": {}, 109 "configuration": {} 110 }`), 111 expected: []FileType{ 112 FileTypeTerraformPlan, 113 FileTypeJSON, 114 }, 115 }, 116 { 117 name: "cloudformation, with reader", 118 path: "main.yaml", 119 r: strings.NewReader(`--- 120 AWSTemplateFormatVersion: 2010-09-09 121 122 Description: CodePipeline for continuous integration and continuous deployment 123 124 Parameters: 125 RepositoryName: 126 Type: String 127 Description: Name of the CodeCommit repository 128 BuildDockerImage: 129 Type: String 130 Default: aws/codebuild/ubuntu-base:14.04 131 Description: Docker image to use for the build phase 132 DeployDockerImage: 133 Type: String 134 Default: aws/codebuild/ubuntu-base:14.04 135 Description: Docker image to use for the deployment phase 136 137 Resources: 138 PipelineS3Bucket: 139 Type: AWS::S3::Bucket 140 `), 141 expected: []FileType{ 142 FileTypeCloudFormation, 143 FileTypeYAML, 144 FileTypeHelm, 145 }, 146 }, 147 { 148 name: "JSON with Resources, not cloudformation", 149 path: "whatever.json", 150 r: strings.NewReader(`{ 151 "Resources": ["something"] 152 }`), 153 expected: []FileType{ 154 FileTypeJSON, 155 }, 156 }, 157 { 158 name: "Dockerfile, no reader", 159 path: "Dockerfile", 160 r: nil, 161 expected: []FileType{ 162 FileTypeDockerfile, 163 }, 164 }, 165 { 166 name: "Containerfile, no reader", 167 path: "Containerfile", 168 r: nil, 169 expected: []FileType{ 170 FileTypeDockerfile, 171 }, 172 }, 173 { 174 name: "Dockerfile, reader", 175 path: "Dockerfile", 176 r: strings.NewReader("FROM ubuntu\n"), 177 expected: []FileType{ 178 FileTypeDockerfile, 179 }, 180 }, 181 { 182 name: "Dockerfile extension", 183 path: "lol.Dockerfile", 184 r: nil, 185 expected: []FileType{ 186 FileTypeDockerfile, 187 }, 188 }, 189 { 190 name: "kubernetes, no reader", 191 path: "k8s.yml", 192 r: nil, 193 expected: []FileType{ 194 FileTypeYAML, 195 }, 196 }, 197 { 198 name: "kubernetes, reader", 199 path: "k8s.yml", 200 r: strings.NewReader(`apiVersion: apps/v1 201 kind: Deployment 202 metadata: 203 name: nginx-deployment 204 labels: 205 app: nginx 206 spec: 207 replicas: 3 208 selector: 209 matchLabels: 210 app: nginx 211 template: 212 metadata: 213 labels: 214 app: nginx 215 spec: 216 containers: 217 - name: nginx 218 image: nginx:1.14.2 219 ports: 220 - containerPort: 80`), 221 expected: []FileType{ 222 FileTypeKubernetes, 223 FileTypeYAML, 224 }, 225 }, 226 { 227 name: "kubernetes, reader, JSON", 228 path: "k8s.json", 229 r: strings.NewReader(`{ 230 "apiVersion": "apps/v1", 231 "kind": "Deployment", 232 "metadata": { 233 "name": "nginx-deployment", 234 "labels": { 235 "app": "nginx" 236 } 237 }, 238 "spec": { 239 "replicas": 3, 240 "selector": { 241 "matchLabels": { 242 "app": "nginx" 243 } 244 }, 245 "template": { 246 "metadata": { 247 "labels": { 248 "app": "nginx" 249 } 250 }, 251 "spec": { 252 "containers": [ 253 { 254 "name": "nginx", 255 "image": "nginx:1.14.2", 256 "ports": [ 257 { 258 "containerPort": 80 259 } 260 ] 261 } 262 ] 263 } 264 } 265 } 266 }`), 267 expected: []FileType{ 268 FileTypeKubernetes, 269 FileTypeJSON, 270 }, 271 }, 272 { 273 name: "YAML, no reader", 274 path: "file.yaml", 275 r: nil, 276 expected: []FileType{ 277 FileTypeYAML, 278 FileTypeHelm, 279 }, 280 }, 281 { 282 name: "YML, no reader", 283 path: "file.yml", 284 r: nil, 285 expected: []FileType{ 286 FileTypeYAML, 287 }, 288 }, 289 { 290 name: "YML uppercase", 291 path: "file.YML", 292 r: nil, 293 expected: []FileType{ 294 FileTypeYAML, 295 }, 296 }, 297 { 298 name: "TOML, no reader", 299 path: "file.toml", 300 r: nil, 301 expected: []FileType{ 302 FileTypeTOML, 303 }, 304 }, 305 { 306 name: "JSON, no reader", 307 path: "file.json", 308 r: nil, 309 expected: []FileType{ 310 FileTypeJSON, 311 }, 312 }, 313 { 314 name: "kubernetes, configmap", 315 path: "k8s.yml", 316 r: strings.NewReader(`apiVersion: v1 317 kind: ConfigMap 318 metadata: 319 name: test 320 namespace: default 321 data: 322 AWS_ACCESS_KEY_ID: "XXX" 323 AWS_SECRET_ACCESS_KEY: "XXX"`), 324 expected: []FileType{ 325 FileTypeKubernetes, 326 FileTypeYAML, 327 }, 328 }, 329 { 330 name: "kubernetes, clusterRole", 331 path: "k8s.yml", 332 r: strings.NewReader(`apiVersion: rbac.authorization.k8s.io/v1 333 kind: ClusterRole 334 metadata: 335 annotations: 336 rbac.authorization.kubernetes.io/autoupdate: "true" 337 labels: 338 kubernetes.io/bootstrapping: rbac-defaults 339 rbac.authorization.k8s.io/aggregate-to-edit: "true" 340 name: view 341 rules: 342 - apiGroups: 343 - networking.k8s.io 344 resources: 345 - ingresses 346 - ingresses/status 347 - networkpolicies 348 verbs: 349 - get 350 - list 351 - watch`), 352 expected: []FileType{ 353 FileTypeKubernetes, 354 FileTypeYAML, 355 }, 356 }, 357 } 358 359 for _, test := range tests { 360 t.Run(test.name, func(t *testing.T) { 361 t.Run("GetTypes", func(t *testing.T) { 362 actualDetections := GetTypes(test.path, test.r) 363 assert.Equal(t, len(test.expected), len(actualDetections)) 364 for _, expected := range test.expected { 365 resetReader(test.r) 366 var found bool 367 for _, actual := range actualDetections { 368 if actual == expected { 369 found = true 370 break 371 } 372 } 373 assert.True(t, found, "%s should be detected", expected) 374 } 375 }) 376 for _, expected := range test.expected { 377 resetReader(test.r) 378 t.Run(fmt.Sprintf("IsType_%s", expected), func(t *testing.T) { 379 assert.True(t, IsType(test.path, test.r, expected)) 380 }) 381 } 382 t.Run("IsType_invalid", func(t *testing.T) { 383 resetReader(test.r) 384 assert.False(t, IsType(test.path, test.r, "invalid")) 385 }) 386 }) 387 } 388 } 389 390 func BenchmarkIsType_SmallFile(b *testing.B) { 391 data, err := os.ReadFile(fmt.Sprintf("./testdata/%s", "small.file")) 392 assert.Nil(b, err) 393 394 b.ReportAllocs() 395 b.ResetTimer() 396 for i := 0; i < b.N; i++ { 397 _ = IsType(fmt.Sprintf("./testdata/%s", "small.file"), bytes.NewReader(data), FileTypeAzureARM) 398 } 399 } 400 401 func BenchmarkIsType_BigFile(b *testing.B) { 402 data, err := os.ReadFile(fmt.Sprintf("./testdata/%s", "big.file")) 403 assert.Nil(b, err) 404 405 b.ReportAllocs() 406 b.ResetTimer() 407 for i := 0; i < b.N; i++ { 408 _ = IsType(fmt.Sprintf("./testdata/%s", "big.file"), bytes.NewReader(data), FileTypeAzureARM) 409 } 410 }