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