github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/checkmarxone/checkmarxone_test.go (about)

     1  package checkmarxOne
     2  
     3  import (
     4  	"bytes"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"strings"
    10  	"testing"
    11  
    12  	piperHttp "github.com/SAP/jenkins-library/pkg/http"
    13  	"github.com/SAP/jenkins-library/pkg/log"
    14  	"github.com/sirupsen/logrus"
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  type senderMock struct {
    19  	token          string
    20  	httpMethod     string
    21  	httpStatusCode int
    22  	urlCalled      string
    23  	requestBody    string
    24  	responseBody   string
    25  	header         http.Header
    26  	logger         *logrus.Entry
    27  	errorExp       bool
    28  }
    29  
    30  func (sm *senderMock) SendRequest(method, url string, body io.Reader, header http.Header, cookies []*http.Cookie) (*http.Response, error) {
    31  	if sm.errorExp {
    32  		return &http.Response{}, errors.New("Provoked technical error")
    33  	}
    34  	sm.httpMethod = method
    35  	sm.urlCalled = url
    36  	sm.header = header
    37  	if body != nil {
    38  		buf := new(bytes.Buffer)
    39  		buf.ReadFrom(body)
    40  		sm.requestBody = buf.String()
    41  	}
    42  	var httpError error
    43  	if sm.httpStatusCode > 399 {
    44  		httpError = fmt.Errorf("http error %v", sm.httpStatusCode)
    45  	}
    46  	return &http.Response{StatusCode: sm.httpStatusCode, Body: io.NopCloser(strings.NewReader(sm.responseBody))}, httpError
    47  }
    48  func (sm *senderMock) UploadFile(url, file, fieldName string, header http.Header, cookies []*http.Cookie, uploadType string) (*http.Response, error) {
    49  	sm.httpMethod = http.MethodPost
    50  	sm.urlCalled = url
    51  	sm.header = header
    52  	return &http.Response{StatusCode: sm.httpStatusCode, Body: io.NopCloser(bytes.NewReader([]byte(sm.responseBody)))}, nil
    53  
    54  }
    55  func (sm *senderMock) UploadRequest(method, url, file, fieldName string, header http.Header, cookies []*http.Cookie, uploadType string) (*http.Response, error) {
    56  	sm.httpMethod = http.MethodPost
    57  	sm.urlCalled = url
    58  	sm.header = header
    59  	return &http.Response{StatusCode: sm.httpStatusCode, Body: io.NopCloser(bytes.NewReader([]byte(sm.responseBody)))}, nil
    60  }
    61  func (sm *senderMock) Upload(_ piperHttp.UploadRequestData) (*http.Response, error) {
    62  	return &http.Response{}, fmt.Errorf("not implemented")
    63  }
    64  func (sm *senderMock) SetOptions(opts piperHttp.ClientOptions) {
    65  	sm.token = opts.Token
    66  }
    67  
    68  func TestSendRequest(t *testing.T) {
    69  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
    70  	opts := piperHttp.ClientOptions{}
    71  	t.Run("test success", func(t *testing.T) {
    72  		myTestClient := senderMock{responseBody: `{"some": "test"}`, httpStatusCode: 200}
    73  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
    74  		myTestClient.SetOptions(opts)
    75  
    76  		_, err := sendRequest(&sys, "GET", "/test", nil, nil, []int{})
    77  
    78  		assert.NoError(t, err, "Error occurred but none expected")
    79  		assert.Equal(t, "https://cx1.server.com/api/test", myTestClient.urlCalled, "Called url incorrect")
    80  	})
    81  
    82  	t.Run("test error", func(t *testing.T) {
    83  		myTestClient := senderMock{responseBody: `{"some": "test"}`, httpStatusCode: 400}
    84  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
    85  		myTestClient.SetOptions(opts)
    86  		_, err := sendRequest(&sys, "GET", "/test", nil, nil, []int{})
    87  
    88  		assert.Error(t, err, "Error expected but none occurred")
    89  		assert.Equal(t, "https://cx1.server.com/api/test", myTestClient.urlCalled, "Called url incorrect")
    90  	})
    91  
    92  	t.Run("test technical error", func(t *testing.T) {
    93  		myTestClient := senderMock{responseBody: `{"some": "test"}`, httpStatusCode: 400}
    94  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
    95  		myTestClient.SetOptions(opts)
    96  		_, err := sendRequest(&sys, "error", "/test", nil, nil, []int{})
    97  
    98  		assert.Error(t, err, "Error expected but none occurred")
    99  	})
   100  }
   101  
   102  func TestSendRequestInternal(t *testing.T) {
   103  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
   104  	opts := piperHttp.ClientOptions{}
   105  
   106  	t.Run("test accepted error", func(t *testing.T) {
   107  		myTestClient := senderMock{responseBody: `{"some": "test"}`, httpStatusCode: 404}
   108  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   109  		myTestClient.SetOptions(opts)
   110  		_, err := sendRequestInternal(&sys, "GET", "/test", nil, nil, []int{404})
   111  
   112  		assert.NoError(t, err, "No error expected but error occurred")
   113  	})
   114  }
   115  
   116  func TestGetOAuthToken(t *testing.T) {
   117  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
   118  	opts := piperHttp.ClientOptions{}
   119  	t.Run("test success", func(t *testing.T) {
   120  		myTestClient := senderMock{responseBody: `{"token_type":"Bearer","access_token":"abcd12345","expires_in":7045634}`, httpStatusCode: 200}
   121  		sys, _ := NewSystemInstance(&myTestClient, "https://cx1.server.com", "https://cx1iam.server.com", "tenant", "", "client", "secret")
   122  		myTestClient.SetOptions(opts)
   123  
   124  		token, err := sys.getOAuth2Token()
   125  
   126  		assert.NoError(t, err, "Error occurred but none expected")
   127  		assert.Equal(t, "https://cx1iam.server.com/auth/realms/tenant/protocol/openid-connect/token", myTestClient.urlCalled, "Called url incorrect")
   128  		assert.Equal(t, "Bearer abcd12345", token, "Token incorrect")
   129  		assert.Equal(t, "client_id=client&client_secret=secret&grant_type=client_credentials", myTestClient.requestBody, "Request body incorrect")
   130  	})
   131  
   132  	t.Run("test authentication failure", func(t *testing.T) {
   133  		myTestClient := senderMock{responseBody: `{}`, httpStatusCode: 400}
   134  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   135  		myTestClient.SetOptions(opts)
   136  
   137  		_, err := sys.getOAuth2Token()
   138  
   139  		assert.Error(t, err, "Error expected but none occurred")
   140  		assert.Equal(t, "https://cx1iam.server.com/auth/realms/tenant/protocol/openid-connect/token", myTestClient.urlCalled, "Called url incorrect")
   141  	})
   142  
   143  	t.Run("test new system", func(t *testing.T) {
   144  		myTestClient := senderMock{responseBody: `{"token_type":"Bearer","access_token":"abcd12345","expires_in":7045634}`, httpStatusCode: 200}
   145  		_, err := NewSystemInstance(&myTestClient, "https://cx1.server.com", "https://cx1iam.server.com", "tenant", "", "client", "secret")
   146  
   147  		assert.NoError(t, err, "Error occurred but none expected")
   148  		assert.Equal(t, "https://cx1iam.server.com/auth/realms/tenant/protocol/openid-connect/token", myTestClient.urlCalled, "Called url incorrect")
   149  		assert.Equal(t, "Bearer abcd12345", myTestClient.token, "Token incorrect")
   150  	})
   151  
   152  	t.Run("test technical error", func(t *testing.T) {
   153  		myTestClient := senderMock{responseBody: `{}`, httpStatusCode: 400}
   154  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   155  		myTestClient.SetOptions(opts)
   156  		myTestClient.errorExp = true
   157  
   158  		_, err := sys.getOAuth2Token()
   159  
   160  		assert.Error(t, err, "Error expected but none occurred")
   161  	})
   162  }
   163  
   164  func TestGetGroups(t *testing.T) {
   165  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
   166  	opts := piperHttp.ClientOptions{}
   167  	t.Run("test success", func(t *testing.T) {
   168  		myTestClient := senderMock{responseBody: `[{"id":"be82031b-a75c-4fc0-894b-fff4deab2854","name":"Group1","path":"/Group1","subGroups":[]},{"id":"b368988c-b124-4151-b507-c8fcad501165","name":"Group2","path":"/Group2","subGroups":[]}]`, httpStatusCode: 200}
   169  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   170  		myTestClient.SetOptions(opts)
   171  
   172  		groups, err := sys.GetGroups()
   173  		assert.NoError(t, err, "Error occurred but none expected")
   174  
   175  		assert.Equal(t, "https://cx1iam.server.com/auth/realms/tenant/pip/groups", myTestClient.urlCalled, "Called url incorrect")
   176  		assert.Equal(t, 2, len(groups), "Number of Groups incorrect")
   177  		assert.Equal(t, "Group1", groups[0].Name, "Group name 1 incorrect")
   178  		assert.Equal(t, "Group2", groups[1].Name, "Group name 2 incorrect")
   179  
   180  		t.Run("test filter groups by name", func(t *testing.T) {
   181  			group2, _ := sys.GetGroupByName("Group2")
   182  			assert.Equal(t, "Group2", group2.Name, "Group name incorrect")
   183  			assert.Equal(t, "b368988c-b124-4151-b507-c8fcad501165", group2.GroupID, "Group id incorrect")
   184  		})
   185  
   186  		t.Run("test Filter groups by ID", func(t *testing.T) {
   187  			group1, _ := sys.GetGroupByID("be82031b-a75c-4fc0-894b-fff4deab2854")
   188  			assert.Equal(t, "Group1", group1.Name, "Group name incorrect")
   189  			assert.Equal(t, "be82031b-a75c-4fc0-894b-fff4deab2854", group1.GroupID, "Group id incorrect")
   190  		})
   191  
   192  		t.Run("test fail Filter groups by name", func(t *testing.T) {
   193  			group, err := sys.GetGroupByName("Group")
   194  			assert.Equal(t, "", group.Name, "Group name incorrect")
   195  			assert.Contains(t, fmt.Sprint(err), "No group matching")
   196  		})
   197  	})
   198  
   199  	t.Run("test technical error", func(t *testing.T) {
   200  		myTestClient := senderMock{responseBody: `[{"id":"1", "fullName":"Group1"}, {"id":"2", "fullName":"Group2"}, {"id":"3", "fullName":"Group3"}]`, httpStatusCode: 200}
   201  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   202  		myTestClient.SetOptions(opts)
   203  		myTestClient.errorExp = true
   204  
   205  		groups, _ := sys.GetGroups()
   206  
   207  		assert.Equal(t, 0, len(groups), "Error expected but none occurred")
   208  	})
   209  }
   210  
   211  func TestGetScanMetadata(t *testing.T) {
   212  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
   213  	opts := piperHttp.ClientOptions{}
   214  	t.Run("test success", func(t *testing.T) {
   215  		myTestClient := senderMock{responseBody: `{"scanId":"03d66397-36df-40b5-8976-f38bcce695a7","projectId":"eac4dc3b-4bbf-4d04-87e5-3b3cedae38fb","loc":158,"fileCount":39,"isIncremental":false,"isIncrementalCanceled":false,"queryPreset":"Checkmarx Default"}`, httpStatusCode: 200}
   216  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   217  		myTestClient.SetOptions(opts)
   218  
   219  		scanmeta, err := sys.GetScanMetadata("03d66397-36df-40b5-8976-f38bcce695a7")
   220  		assert.NoError(t, err, "Error occurred but none expected")
   221  
   222  		assert.Equal(t, "03d66397-36df-40b5-8976-f38bcce695a7", scanmeta.ScanID, "ScanID is incorrect")
   223  		assert.Equal(t, "eac4dc3b-4bbf-4d04-87e5-3b3cedae38fb", scanmeta.ProjectID, "ProjectID is incorrect")
   224  		assert.Equal(t, 158, scanmeta.LOC, "LOC is incorrect")
   225  		assert.Equal(t, 39, scanmeta.FileCount, "FileCount is incorrect")
   226  		assert.Equal(t, false, scanmeta.IsIncremental, "IsIncremental is incorrect")
   227  		assert.Equal(t, false, scanmeta.IsIncrementalCanceled, "IsIncrementalCanceled is incorrect")
   228  		assert.Equal(t, "Checkmarx Default", scanmeta.PresetName, "PresetName is incorrect")
   229  	})
   230  
   231  	t.Run("test technical error", func(t *testing.T) {
   232  		myTestClient := senderMock{httpStatusCode: 200}
   233  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   234  		myTestClient.SetOptions(opts)
   235  		myTestClient.errorExp = true
   236  
   237  		_, err := sys.GetScanMetadata("03d66397-36df-40b5-8976-f38bcce695a7")
   238  		assert.Contains(t, fmt.Sprint(err), "Provoked technical error")
   239  	})
   240  }
   241  
   242  func TestGetScan(t *testing.T) {
   243  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
   244  	opts := piperHttp.ClientOptions{}
   245  	t.Run("test success", func(t *testing.T) {
   246  		myTestClient := senderMock{responseBody: `{"id":"7343f9f5-7633-40d5-b000-0a7a3c2c432e","status":"Completed","statusDetails":[{"name":"general","status":"Completed","details":""},{"name":"sast","status":"Completed","details":"","loc":2148}],"branch":"master","createdAt":"2023-03-31T08:35:56.412514Z","updatedAt":"2023-03-31T08:36:53.526569Z","projectId":"e7a7704c-4bfe-4054-9137-d32c156ca641","projectName":"fullScanCycle","userAgent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0","initiator":"user@sap.com","tags":{},"metadata":{"id":"7343f9f5-7633-40d5-b000-0a7a3c2c432e","type":"upload","Handler":{"UploadHandler":{"branch":"master","upload_url":"https://cx1.server.com/storage/st-gcp-9k90xv-uploads/b68ee5ba-3657-424f-9b68-05452300d5d7/271b80e3-b0d4-4be6-9f66-9469126b624f?X-Amz-Algorithm=AWS4-HMAC-SHA256\u0026X-Amz-Credential=ast%2F20230331%2Fus-east-1%2Fs3%2Faws4_request\u0026X-Amz-Date=20230331T083556Z\u0026X-Amz-Expires=86400\u0026X-Amz-Signature=94d74276d93945c37243f7ccec3d1e30b15d4d6ec79a869d3d9e46622fd89acd\u0026X-Amz-SignedHeaders=host"}},"configs":[{"type":"sast","value":{"presetName":"Checkmarx Default","incremental":"true","languageMode":"primary"}}],"project":{"id":"e7a7704c-4bfe-4054-9137-d32c156ca641"},"created_at":{"nanos":387074846,"seconds":1680251756}},"engines":["sast"],"sourceType":"zip","sourceOrigin":"Mozilla"}`, httpStatusCode: 200}
   247  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   248  		myTestClient.SetOptions(opts)
   249  
   250  		scan, err := sys.GetScan("7343f9f5-7633-40d5-b000-0a7a3c2c432e")
   251  		assert.NoError(t, err, "Error occurred but none expected")
   252  		assert.Equal(t, "7343f9f5-7633-40d5-b000-0a7a3c2c432e", scan.ScanID, "ScanID is incorrect")
   253  		assert.Equal(t, "master", scan.Branch, "Branch is incorrect")
   254  		assert.Equal(t, 2, len(scan.StatusDetails), "StatusDetails is incorrect")
   255  	})
   256  
   257  	t.Run("test technical error", func(t *testing.T) {
   258  		myTestClient := senderMock{httpStatusCode: 200}
   259  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   260  		myTestClient.SetOptions(opts)
   261  		myTestClient.errorExp = true
   262  
   263  		_, err := sys.GetScan("7343f9f5-7633-40d5-b000-0a7a3c2c432e")
   264  		assert.Contains(t, fmt.Sprint(err), "Provoked technical error")
   265  	})
   266  }
   267  
   268  func TestGetApplicationByName(t *testing.T) {
   269  	logger := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne_test")
   270  	opts := piperHttp.ClientOptions{}
   271  	t.Run("test success", func(t *testing.T) {
   272  		myTestClient := senderMock{responseBody: `{"totalCount":6,"filteredTotalCount":6,"applications":[{"id":"8cf83fcf-ac61-4e32-b988-47cde3cc818c","name":"test_dev2","description":"","criticality":3,"rules":[],"projectIds":[],"tags":{},"createdAt":"2023-04-06T13:57:00.082719Z","updatedAt":"2023-04-06T13:57:00.082719Z"},{"id":"dee8573b-c58e-4945-a97c-a66884380093","name":"test_dev1","description":"","criticality":3,"rules":[],"projectIds":[],"tags":{},"createdAt":"2023-04-06T13:44:32.212065Z","updatedAt":"2023-04-06T13:44:32.212065Z"},{"id":"0ff00c77-b7e6-4d27-bd88-9e14520e06e6","name":"test_dev","description":"","criticality":3,"rules":[],"projectIds":[],"tags":{},"createdAt":"2023-04-06T13:24:36.459375Z","updatedAt":"2023-04-06T13:24:36.459375Z"},{"id":"5d482cfc-27ae-43e1-ba45-68d557df8423","name":"SSBA","description":"","criticality":3,"rules":[{"id":"e00a5b13-93d0-4128-8c32-9d6a46db85b0","type":"project.name.in","value":"ssba-zip;ssba-git;cx_cli_ssba_test"}],"projectIds":["2d75e828-6db9-4cfa-87e7-b953ad59ea25","f00a9d02-b552-4461-835a-c701e30957d8","f61cf5f0-fa91-4563-b87b-8154a4fd2408"],"tags":{},"createdAt":"2023-03-15T13:44:31.831175Z","updatedAt":"2023-03-15T13:44:31.831175Z"},{"id":"68f2f996-e7eb-495e-8829-8996241eb84e","name":"test_1","description":"","criticality":3,"rules":[{"id":"3a08b06e-a76a-4a48-bcde-1b43b9890f31","type":"project.name.in","value":"OAuth-CLI-test;test-piper-1;cx_cli_ssba_test"}],"projectIds":["2d75e828-6db9-4cfa-87e7-b953ad59ea25","db82605a-26e4-4693-a59c-ec1d584840d0","31c44a7c-0c68-492a-9921-052d336e5d5a"],"tags":{"TEST_APP":""},"createdAt":"2023-02-20T13:12:02.927562Z","updatedAt":"2023-02-20T13:12:02.927562Z"},{"id":"095dced0-60b0-4dd6-b1e8-0063fa04eaa7","name":"TEST","description":"","criticality":3,"rules":[{"id":"fc02a324-0706-4522-a89f-e24bcbf76cf7","type":"project.tag.key.exists","value":"test"}],"projectIds":["db82605a-26e4-4693-a59c-ec1d584840d0"],"tags":{"TEST_APP":""},"createdAt":"2023-01-12T13:22:38.222789Z","updatedAt":"2023-01-12T13:22:38.222789Z"}]}`, httpStatusCode: 200}
   273  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   274  		myTestClient.SetOptions(opts)
   275  
   276  		apps, err := sys.GetApplicationsByName("test", 10)
   277  		assert.NoError(t, err, "Error occurred but none expected")
   278  		assert.Equal(t, 6, len(apps), "TotalCount is incorrect")
   279  
   280  		app1, _ := sys.GetApplicationByName("test_dev2")
   281  		assert.Equal(t, "8cf83fcf-ac61-4e32-b988-47cde3cc818c", app1.ApplicationID, "ApplicationID is incorrect")
   282  
   283  		_, err = sys.GetApplicationByName("ssba")
   284  		assert.Contains(t, fmt.Sprint(err), "no application found named ssba")
   285  	})
   286  
   287  	t.Run("test technical error", func(t *testing.T) {
   288  		myTestClient := senderMock{httpStatusCode: 200}
   289  		sys := SystemInstance{serverURL: "https://cx1.server.com", iamURL: "https://cx1iam.server.com", tenant: "tenant", client: &myTestClient, logger: logger}
   290  		myTestClient.SetOptions(opts)
   291  		myTestClient.errorExp = true
   292  
   293  		_, err := sys.GetApplicationsByName("test", 10)
   294  		assert.Contains(t, fmt.Sprint(err), "Provoked technical error")
   295  	})
   296  }