Skip to content

Commit aac0933

Browse files
frjcompCopilot
andauthored
Tests (#311)
* Refactored Code base and implemented E2E and unit base tests --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent 5bdacc4 commit aac0933

117 files changed

Lines changed: 14042 additions & 2036 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,19 @@ jobs:
2020
with:
2121
go-version: stable
2222

23-
- name: Run tests
23+
- name: Run unit tests
2424
working-directory: ./src/pipeleak
25-
run: go test ./... -v -race -coverprofile=coverage.out -covermode=atomic
25+
run: go test $(go list ./... | grep -v /tests/e2e) -v -race -coverprofile=coverage.out -covermode=atomic
26+
27+
- name: Build pipeleak binary for e2e tests
28+
working-directory: ./src/pipeleak
29+
run: go build -o pipeleak .
30+
31+
- name: Run e2e tests
32+
working-directory: ./src/pipeleak
33+
run: go test ./tests/e2e/... -v -timeout 10m
34+
env:
35+
PIPELEAK_BINARY: ./pipeleak
2636

2737
- name: Display coverage
2838
working-directory: ./src/pipeleak

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ renovate-enum-out
55
cli-docs
66
site
77
src/pipeleak/pipeleak
8+
.vscode

src/pipeleak/cmd/bitbucket/api.go

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,33 @@ import (
1616

1717
// Docs: https://developer.atlassian.com/cloud/bitbucket/rest/intro/
1818
type BitBucketApiClient struct {
19-
Client resty.Client
19+
Client resty.Client
20+
BaseURL string
21+
InternalBaseURL string
2022
}
2123

22-
func NewClient(username string, password string, bitBucketCookie string) BitBucketApiClient {
24+
func NewClient(username string, password string, bitBucketCookie string, baseURL string) BitBucketApiClient {
25+
if baseURL == "" {
26+
baseURL = "https://api.bitbucket.org/2.0"
27+
}
28+
// Derive an internal base URL for BitBucket internal APIs (bitbucket.org/!api/...)
29+
// Default behaviour: if API base points to api.bitbucket.org use bitbucket.org for internal endpoints
30+
parsedBase, err := url.Parse(baseURL)
31+
if err != nil {
32+
log.Fatal().Err(err).Msg("Unable to parse baseURL")
33+
}
34+
35+
internalHost := parsedBase.Host
36+
if parsedBase.Host == "api.bitbucket.org" || parsedBase.Host == "api.bitbucket.org:443" {
37+
internalHost = "bitbucket.org"
38+
}
39+
internalBase := parsedBase.Scheme + "://" + internalHost + "/!api"
40+
2341
client := *resty.New().SetBasicAuth(username, password).SetRedirectPolicy(resty.FlexibleRedirectPolicy(5))
2442
if len(bitBucketCookie) > 0 {
2543
jar, _ := cookiejar.New(nil)
26-
targetURL, _ := url.Parse("https://bitbucket.org/")
44+
// set cookie on the internal host root so requests to internal endpoints include it
45+
targetURL := &url.URL{Scheme: parsedBase.Scheme, Host: internalHost, Path: "/"}
2746
jar.SetCookies(targetURL, []*http.Cookie{
2847
{
2948
Name: "cloud.session.token",
@@ -35,7 +54,7 @@ func NewClient(username string, password string, bitBucketCookie string) BitBuck
3554
log.Debug().Msg("Added cloud.session.token to HTTP client")
3655
}
3756

38-
bbClient := BitBucketApiClient{Client: client}
57+
bbClient := BitBucketApiClient{Client: client, BaseURL: baseURL, InternalBaseURL: internalBase}
3958
bbClient.Client.AddRetryHooks(
4059
func(res *resty.Response, err error) {
4160
if res.StatusCode() == 429 {
@@ -50,7 +69,7 @@ func NewClient(username string, password string, bitBucketCookie string) BitBuck
5069

5170
// https://developer.atlassian.com/cloud/bitbucket/rest/api-group-workspaces/#api-workspaces-get
5271
func (a BitBucketApiClient) ListOwnedWorkspaces(nextPageUrl string) ([]Workspace, string, *resty.Response, error) {
53-
url := "https://api.bitbucket.org/2.0/workspaces"
72+
url := a.BaseURL + "/workspaces"
5473
if nextPageUrl != "" {
5574
url = nextPageUrl
5675
}
@@ -77,7 +96,7 @@ func (a BitBucketApiClient) ListWorkspaceRepositoires(nextPageUrl string, worksp
7796
if nextPageUrl != "" {
7897
reqUrl = nextPageUrl
7998
} else {
80-
u, err := url.Parse("https://api.bitbucket.org/2.0/repositories/")
99+
u, err := url.Parse(a.BaseURL + "/repositories/")
81100
if err != nil {
82101
log.Fatal().Err(err).Msg("Unable to parse ListWorkspaceRepositoires url")
83102
}
@@ -108,7 +127,7 @@ func (a BitBucketApiClient) ListPublicRepositories(nextPageUrl string, after tim
108127
if nextPageUrl != "" {
109128
reqUrl = nextPageUrl
110129
} else {
111-
u, err := url.Parse("https://api.bitbucket.org/2.0/repositories/")
130+
u, err := url.Parse(a.BaseURL + "/repositories/")
112131
if err != nil {
113132
log.Fatal().Err(err).Msg("Unable to parse ListPublicRepositories url")
114133
}
@@ -147,7 +166,7 @@ func (a BitBucketApiClient) ListRepositoryPipelines(nextPageUrl string, workspac
147166
if nextPageUrl != "" {
148167
reqUrl = nextPageUrl
149168
} else {
150-
u, err := url.Parse("https://api.bitbucket.org/2.0/repositories/")
169+
u, err := url.Parse(a.BaseURL + "/repositories/")
151170
if err != nil {
152171
log.Fatal().Err(err).Msg("Unable to parse ListRepositoryPipelines url")
153172
}
@@ -183,7 +202,7 @@ func (a BitBucketApiClient) ListPipelineSteps(nextPageUrl string, workspaceSlug
183202
if nextPageUrl != "" {
184203
reqUrl = nextPageUrl
185204
} else {
186-
u, err := url.Parse("https://api.bitbucket.org/2.0/repositories/")
205+
u, err := url.Parse(a.BaseURL + "/repositories/")
187206
if err != nil {
188207
log.Fatal().Err(err).Msg("Unable to parse ListPipelineSteps url")
189208
}
@@ -209,7 +228,7 @@ func (a BitBucketApiClient) ListPipelineSteps(nextPageUrl string, workspaceSlug
209228

210229
// https://developer.atlassian.com/cloud/bitbucket/rest/api-group-pipelines/#api-repositories-workspace-repo-slug-pipelines-pipeline-uuid-steps-step-uuid-log-get
211230
func (a BitBucketApiClient) GetStepLog(workspaceSlug string, repoSlug string, pipelineUUID string, stepUUID string) ([]byte, *resty.Response, error) {
212-
u, err := url.Parse("https://api.bitbucket.org/2.0/repositories/")
231+
u, err := url.Parse(a.BaseURL + "/repositories/")
213232
if err != nil {
214233
log.Fatal().Err(err).Msg("Unable to parse GetStepLog url")
215234
}
@@ -240,7 +259,7 @@ func (a BitBucketApiClient) ListDownloadArtifacts(nextPageUrl string, workspaceS
240259
if nextPageUrl != "" {
241260
reqUrl = nextPageUrl
242261
} else {
243-
u, err := url.Parse("https://api.bitbucket.org/2.0/repositories/")
262+
u, err := url.Parse(a.BaseURL + "/repositories/")
244263
if err != nil {
245264
log.Fatal().Err(err).Msg("Unable to parse ListDownloadArtifacts url")
246265
}
@@ -291,7 +310,7 @@ func (a BitBucketApiClient) ListPipelineArtifacts(nextPageUrl string, workspaceS
291310
if nextPageUrl != "" {
292311
reqUrl = nextPageUrl
293312
} else {
294-
u, err := url.Parse("https://bitbucket.org/!api/internal/repositories/")
313+
u, err := url.Parse(a.InternalBaseURL + "/internal/repositories/")
295314
if err != nil {
296315
log.Fatal().Err(err).Msg("Unable to parse ListPipelineArtifacst url")
297316
}
@@ -309,8 +328,7 @@ func (a BitBucketApiClient) ListPipelineArtifacts(nextPageUrl string, workspaceS
309328

310329
// Internal API: https://bitbucket.org/!api/internal/repositories/{workspace}/{repo}/pipelines/{buildId}/artifacts/{ArtifactUUID}/content
311330
func (a BitBucketApiClient) GetPipelineArtifact(workspaceSlug string, repoSlug string, buildNumber int, artifactUUID string) []byte {
312-
313-
u, err := url.Parse("https://bitbucket.org/!api/internal/repositories/")
331+
u, err := url.Parse(a.InternalBaseURL + "/internal/repositories/")
314332
if err != nil {
315333
log.Fatal().Err(err).Msg("Unable to parse GetPipelineArtifact url")
316334
}
@@ -336,7 +354,7 @@ func (a BitBucketApiClient) GetuserInfo() {
336354
resp := &UserInfo{}
337355
res, err := a.Client.R().
338356
SetResult(resp).
339-
Get("https://bitbucket.org/!api/2.0/user")
357+
Get(a.InternalBaseURL + "/2.0/user")
340358

341359
if err != nil {
342360
log.Error().Err(err).Msg("Failed get user info (network or client error)")
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package processor
2+
3+
import (
4+
"github.com/CompassSecurity/pipeleak/pkg/scanner"
5+
"github.com/h2non/filetype"
6+
)
7+
8+
type StepLogResult struct {
9+
WorkspaceSlug string
10+
RepoSlug string
11+
PipelineUUID string
12+
StepUUID string
13+
Findings []scanner.Finding
14+
Error error
15+
}
16+
17+
func ProcessStepLogs(logBytes []byte, workspaceSlug, repoSlug, pipelineUUID, stepUUID string, maxGoRoutines int, verifyCredentials bool) (*StepLogResult, error) {
18+
result := &StepLogResult{
19+
WorkspaceSlug: workspaceSlug,
20+
RepoSlug: repoSlug,
21+
PipelineUUID: pipelineUUID,
22+
StepUUID: stepUUID,
23+
}
24+
25+
findings, err := scanner.DetectHits(logBytes, maxGoRoutines, verifyCredentials)
26+
if err != nil {
27+
result.Error = err
28+
return result, err
29+
}
30+
31+
result.Findings = findings
32+
return result, nil
33+
}
34+
35+
type ArtifactResult struct {
36+
Filename string
37+
DownloadURL string
38+
WebURL string
39+
IsArchive bool
40+
ProcessedFile bool
41+
Error error
42+
}
43+
44+
func ProcessArtifactContent(fileBytes []byte, filename, webURL string, verifyCredentials bool) *ArtifactResult {
45+
result := &ArtifactResult{
46+
Filename: filename,
47+
WebURL: webURL,
48+
}
49+
50+
if len(fileBytes) == 0 {
51+
return result
52+
}
53+
54+
if filetype.IsArchive(fileBytes) {
55+
result.IsArchive = true
56+
scanner.HandleArchiveArtifact(filename, fileBytes, webURL, "Download Artifact", verifyCredentials)
57+
result.ProcessedFile = true
58+
} else {
59+
result.IsArchive = false
60+
scanner.DetectFileHits(fileBytes, webURL, "Download Artifact", filename, "", verifyCredentials)
61+
result.ProcessedFile = true
62+
}
63+
64+
return result
65+
}
66+
67+
func ShouldContinueScanning(currentCount, maxLimit int) bool {
68+
if maxLimit <= 0 {
69+
return true
70+
}
71+
return currentCount < maxLimit
72+
}

0 commit comments

Comments
 (0)