diff --git a/examples/.examples-ci.yml b/examples/.examples-ci.yml index a7ffdae9..5cdb845f 100644 --- a/examples/.examples-ci.yml +++ b/examples/.examples-ci.yml @@ -12,8 +12,9 @@ go-sdk-examples: - file_scan - intel - redact - - vault + - sanitize - share + - vault image: golang:${GO_VERSION} before_script: - export PANGEA_AUDIT_CONFIG_ID="${PANGEA_AUDIT_CONFIG_ID_1_LVE_AWS}" @@ -32,10 +33,11 @@ go-sdk-examples: - export PANGEA_REDACT_CONFIG_ID="${PANGEA_REDACT_CONFIG_ID_1_LVE_AWS}" - export PANGEA_REDACT_MULTICONFIG_TOKEN="${PANGEA_INTEGRATION_MULTI_CONFIG_TOKEN_LVE_AWS}" - export PANGEA_REDACT_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" + - export PANGEA_SANITIZE_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" + - export PANGEA_SHARE_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" - export PANGEA_URL_INTEL_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" - export PANGEA_USER_INTEL_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" - export PANGEA_VAULT_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" - - export PANGEA_SHARE_TOKEN="${PANGEA_INTEGRATION_TOKEN_LVE_AWS}" script: - cd examples/${EXAMPLE_FOLDER} - bash ../../dev/run_examples.sh diff --git a/examples/sanitize/go.mod b/examples/sanitize/go.mod new file mode 100644 index 00000000..dcc493ab --- /dev/null +++ b/examples/sanitize/go.mod @@ -0,0 +1,14 @@ +module examples/sanitize + +go 1.22 + +require github.com/pangeacyber/pangea-go/pangea-sdk/v4 v4.1.0 + +require ( + github.com/hashicorp/go-cleanhttp v0.5.2 // indirect + github.com/hashicorp/go-retryablehttp v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/rs/zerolog v1.33.0 // indirect + golang.org/x/sys v0.26.0 // indirect +) diff --git a/examples/sanitize/go.sum b/examples/sanitize/go.sum new file mode 100644 index 00000000..9a91f6cf --- /dev/null +++ b/examples/sanitize/go.sum @@ -0,0 +1,35 @@ +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= +github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= +github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU= +github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/pangeacyber/pangea-go/pangea-sdk/v4 v4.1.0 h1:GbwAZyhNqUph/n/tvxaCyna+sVOojJsiXFe7PkbR7t8= +github.com/pangeacyber/pangea-go/pangea-sdk/v4 v4.1.0/go.mod h1:5XIW52PITcGiggsoSVoFstTlF/5cU51sywvBD5gB6pk= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/examples/sanitize/sanitize_and_share.go b/examples/sanitize/sanitize_and_share.go new file mode 100644 index 00000000..24bb4d94 --- /dev/null +++ b/examples/sanitize/sanitize_and_share.go @@ -0,0 +1,106 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/pangea" + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/service/sanitize" +) + +func main() { + // Set filePath to your own file + const filePath = "./testdata/ds11.pdf" + + // Load Pangea token from environment variables + token := os.Getenv("PANGEA_SANITIZE_TOKEN") + if token == "" { + log.Fatal("Unauthorized: No token present.") + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second) + defer cancelFn() + + // Create a new Sanitize client with Pangea token and domain + client := sanitize.New(&pangea.Config{ + Token: token, + Domain: os.Getenv("PANGEA_DOMAIN"), + QueuedRetryEnabled: true, + PollResultTimeout: 120 * time.Second, + Retry: true, + RetryConfig: &pangea.RetryConfig{ + RetryMax: 4, + }, + }) + + file, err := os.Open(filePath) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Get file upload params + params, err := pangea.GetUploadFileParams(file) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Create a SanitizeRequest. + // In this case TransferMethod is set to TMpostURL + // Set CRC32C, SHA256 and Size + input := &sanitize.SanitizeRequest{ + Content: &sanitize.SanitizeContent{ + URLIntel: pangea.Bool(true), + URLIntelProvider: "crowdstrike", + DomainIntel: pangea.Bool(true), + DomainIntelProvider: "crowdstrike", + Defang: pangea.Bool(true), + DefangThreshold: pangea.Int(20), + RemoveInteractive: pangea.Bool(true), + RemoveAttachments: pangea.Bool(true), + Redact: pangea.Bool(true), + }, + // Enable Secure Share output and set output folder + ShareOutput: &sanitize.SanitizeShareOutput{ + Enabled: pangea.Bool(true), + OutputFolder: "sdk_test/sanitize/", + }, + File: &sanitize.SanitizeFile{ + ScanProvider: "crowdstrike", + }, + UploadedFileName: "uploaded_file", + TransferRequest: pangea.TransferRequest{ + TransferMethod: pangea.TMpostURL, + }, + SHA256: params.SHA256, + CRC32C: params.CRC32C, + Size: pangea.Int(params.Size), + } + + fmt.Println("Sending Sanitize request...") + resp, err := client.Sanitize(ctx, input, file) + if err != nil { + log.Fatalf("Failed to process Sanitize request. Unexpected error: %v", err.Error()) + } + + fmt.Println("File Sanitized:") + if resp.Result.DestShareID != nil { + fmt.Printf("\tShare ID: %s\n", *resp.Result.DestShareID) + } + if resp.Result.DestURL != nil { + fmt.Printf("\tDest URL: %s\n", *resp.Result.DestURL) + } + + fmt.Printf("\tRedact data: %s\n", pangea.Stringify(resp.Result.Data.Redact)) + fmt.Printf("\tDefang data: %s\n", pangea.Stringify(resp.Result.Data.Defang)) + fmt.Printf("\tCDR data: %s\n", pangea.Stringify(resp.Result.Data.CDR)) + + if resp.Result.Data.MaliciousFile { + fmt.Println("File IS malicious") + } else { + fmt.Println("File is NOT malicious") + } + +} diff --git a/examples/sanitize/sanitize_multipart.go b/examples/sanitize/sanitize_multipart.go new file mode 100644 index 00000000..face5898 --- /dev/null +++ b/examples/sanitize/sanitize_multipart.go @@ -0,0 +1,96 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/pangea" + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/service/sanitize" +) + +func main() { + // Set filePath to your own file + const filePath = "./testdata/ds11.pdf" + + // Load Pangea token from environment variables + token := os.Getenv("PANGEA_SANITIZE_TOKEN") + if token == "" { + log.Fatal("Unauthorized: No token present.") + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second) + defer cancelFn() + + // Create a new Sanitize client with Pangea token and domain + client := sanitize.New(&pangea.Config{ + Token: token, + Domain: os.Getenv("PANGEA_DOMAIN"), + QueuedRetryEnabled: true, + PollResultTimeout: 120 * time.Second, + Retry: true, + RetryConfig: &pangea.RetryConfig{ + RetryMax: 4, + }, + }) + + file, err := os.Open(filePath) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Create a SanitizeRequest. + // In this case TransferMethod is set to TMmultipartURL + input := &sanitize.SanitizeRequest{ + Content: &sanitize.SanitizeContent{ + URLIntel: pangea.Bool(true), + URLIntelProvider: "crowdstrike", + DomainIntel: pangea.Bool(true), + DomainIntelProvider: "crowdstrike", + Defang: pangea.Bool(true), + DefangThreshold: pangea.Int(20), + RemoveInteractive: pangea.Bool(true), + RemoveAttachments: pangea.Bool(true), + Redact: pangea.Bool(true), + }, + // Enable Secure Share output and set output folder + ShareOutput: &sanitize.SanitizeShareOutput{ + Enabled: pangea.Bool(true), + OutputFolder: "sdk_test/sanitize/", + }, + File: &sanitize.SanitizeFile{ + ScanProvider: "crowdstrike", + }, + UploadedFileName: "uploaded_file", + TransferRequest: pangea.TransferRequest{ + TransferMethod: pangea.TMmultipart, + }, + } + + fmt.Println("Sending Sanitize request as multipart...") + resp, err := client.Sanitize(ctx, input, file) + if err != nil { + log.Fatalf("Failed to process Sanitize request. Unexpected error: %v", err.Error()) + } + + fmt.Println("File Sanitized:") + if resp.Result.DestShareID != nil { + fmt.Printf("\tShare ID: %s\n", *resp.Result.DestShareID) + } + if resp.Result.DestURL != nil { + fmt.Printf("\tDest URL: %s\n", *resp.Result.DestURL) + } + + fmt.Printf("\tRedact data: %s\n", pangea.Stringify(resp.Result.Data.Redact)) + fmt.Printf("\tDefang data: %s\n", pangea.Stringify(resp.Result.Data.Defang)) + fmt.Printf("\tCDR data: %s\n", pangea.Stringify(resp.Result.Data.CDR)) + + if resp.Result.Data.MaliciousFile { + fmt.Println("File IS malicious") + } else { + fmt.Println("File is NOT malicious") + } + +} diff --git a/examples/sanitize/sanitize_no_share.go b/examples/sanitize/sanitize_no_share.go new file mode 100644 index 00000000..e953fa2b --- /dev/null +++ b/examples/sanitize/sanitize_no_share.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/pangea" + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/service/sanitize" +) + +func main() { + // Set filePath to your own file + const filePath = "./testdata/ds11.pdf" + + // Load Pangea token from environment variables + token := os.Getenv("PANGEA_SANITIZE_TOKEN") + if token == "" { + log.Fatal("Unauthorized: No token present.") + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second) + defer cancelFn() + + // create a new sanitize client with pangea token and domain + client := sanitize.New(&pangea.Config{ + Token: token, + Domain: os.Getenv("PANGEA_DOMAIN"), + QueuedRetryEnabled: true, + PollResultTimeout: 120 * time.Second, + Retry: true, + RetryConfig: &pangea.RetryConfig{ + RetryMax: 4, + }, + }) + + file, err := os.Open(filePath) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Get file upload params + params, err := pangea.GetUploadFileParams(file) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Create a SanitizeRequest. + // In this case TransferMethod is set to TMpostURL + // Set CRC32C, SHA256 and Size + input := &sanitize.SanitizeRequest{ + Content: &sanitize.SanitizeContent{ + URLIntel: pangea.Bool(true), + URLIntelProvider: "crowdstrike", + DomainIntel: pangea.Bool(true), + DomainIntelProvider: "crowdstrike", + Defang: pangea.Bool(true), + DefangThreshold: pangea.Int(20), + RemoveInteractive: pangea.Bool(true), + RemoveAttachments: pangea.Bool(true), + Redact: pangea.Bool(true), + }, + // Disable Secure Share output + ShareOutput: &sanitize.SanitizeShareOutput{ + Enabled: pangea.Bool(false), + }, + File: &sanitize.SanitizeFile{ + ScanProvider: "crowdstrike", + }, + UploadedFileName: "uploaded_file", + TransferRequest: pangea.TransferRequest{ + TransferMethod: pangea.TMpostURL, + }, + SHA256: params.SHA256, + CRC32C: params.CRC32C, + Size: pangea.Int(params.Size), + } + + fmt.Println("Sending Sanitize request...") + resp, err := client.Sanitize(ctx, input, file) + if err != nil { + log.Fatalf("Failed to process Sanitize request. Unexpected error: %v", err.Error()) + } + + fmt.Println("File Sanitized:") + if resp.Result.DestShareID != nil { + fmt.Printf("\tShare ID: %s\n", *resp.Result.DestShareID) + } + if resp.Result.DestURL != nil { + fmt.Printf("\tDest URL: %s\n", *resp.Result.DestURL) + } + + fmt.Printf("\tRedact data: %s\n", pangea.Stringify(resp.Result.Data.Redact)) + fmt.Printf("\tDefang data: %s\n", pangea.Stringify(resp.Result.Data.Defang)) + fmt.Printf("\tCDR data: %s\n", pangea.Stringify(resp.Result.Data.CDR)) + + if resp.Result.Data.MaliciousFile { + fmt.Println("File IS malicious") + } else { + fmt.Println("File is NOT malicious") + } + +} diff --git a/examples/sanitize/sanitize_split_upload_post_url.go b/examples/sanitize/sanitize_split_upload_post_url.go new file mode 100644 index 00000000..536687b3 --- /dev/null +++ b/examples/sanitize/sanitize_split_upload_post_url.go @@ -0,0 +1,151 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/pangea" + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/service/sanitize" +) + +func main() { + // Set filePath to your own file + const filePath = "./testdata/ds11.pdf" + + // Load Pangea token from environment variables + token := os.Getenv("PANGEA_SANITIZE_TOKEN") + if token == "" { + log.Fatal("Unauthorized: No token present.") + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second) + defer cancelFn() + + // Create a new Sanitize client with Pangea token and domain + client := sanitize.New(&pangea.Config{ + Token: token, + Domain: os.Getenv("PANGEA_DOMAIN"), + QueuedRetryEnabled: true, + PollResultTimeout: 120 * time.Second, + Retry: true, + RetryConfig: &pangea.RetryConfig{ + RetryMax: 4, + }, + }) + + file, err := os.Open(filePath) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Get file upload params + params, err := pangea.GetUploadFileParams(file) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + // Create a SanitizeRequest to request an presigned upload url. + // In this case TransferMethod is set to TMpostURL + // Set CRC32C, SHA256 and Size + input := &sanitize.SanitizeRequest{ + Content: &sanitize.SanitizeContent{ + URLIntel: pangea.Bool(true), + URLIntelProvider: "crowdstrike", + DomainIntel: pangea.Bool(true), + DomainIntelProvider: "crowdstrike", + Defang: pangea.Bool(true), + DefangThreshold: pangea.Int(20), + RemoveInteractive: pangea.Bool(true), + RemoveAttachments: pangea.Bool(true), + Redact: pangea.Bool(true), + }, + ShareOutput: &sanitize.SanitizeShareOutput{ + Enabled: pangea.Bool(true), + OutputFolder: "sdk_test/sanitize/", + }, + File: &sanitize.SanitizeFile{ + ScanProvider: "crowdstrike", + }, + UploadedFileName: "uploaded_file", + TransferRequest: pangea.TransferRequest{ + TransferMethod: pangea.TMpostURL, + }, + SHA256: params.SHA256, + CRC32C: params.CRC32C, + Size: pangea.Int(params.Size), + } + + fmt.Println("Request upload URL...") + resp, err := client.RequestUploadURL(ctx, input) + if err != nil { + log.Fatalf("Failed to get upload URL. Unexpected error: %v", err.Error()) + } + + // Get presigned url and data to post + url := resp.AcceptedResult.PostURL + data := resp.AcceptedResult.PostFormData + fmt.Printf("Got URL: %s\n", url) + + fd := pangea.FileData{ + File: file, + Details: data, + Name: "someName", + } + + // Create an uploader + uploader := pangea.NewFileUploader() + + fmt.Println("Uploading file...") + // Upload the file to the returned upload URL. + // Need to set transfer method again to TMpostURL + err = uploader.UploadFile(ctx, url, pangea.TMpostURL, fd) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + var sr *pangea.PangeaResponse[any] + i := 0 + maxRetry := 24 + + // Try to poll result + for i < maxRetry { + // Wait until result should be ready + time.Sleep(time.Duration(10 * time.Second)) + fmt.Printf("Trying to poll result. Retry: %d\n", i) + sr, err = client.PollResultByID(ctx, *resp.RequestID, &sanitize.SanitizeResult{}) + if err == nil { + break + } + i++ + fmt.Println("Result is not ready yet. Retrying...") + } + + if i >= maxRetry { + log.Fatal("Failed to poll result. Max retry reached.") + } + + // After receiving the result, cast it before using it. + rSanitize := (*sr.Result).(*sanitize.SanitizeResult) + + fmt.Println("File Sanitized:") + if rSanitize.DestShareID != nil { + fmt.Printf("\tShare ID: %s\n", *rSanitize.DestShareID) + } + if rSanitize.DestURL != nil { + fmt.Printf("\tDest URL: %s\n", *rSanitize.DestURL) + } + + fmt.Printf("\tRedact data: %s\n", pangea.Stringify(rSanitize.Data.Redact)) + fmt.Printf("\tDefang data: %s\n", pangea.Stringify(rSanitize.Data.Defang)) + fmt.Printf("\tCDR data: %s\n", pangea.Stringify(rSanitize.Data.CDR)) + + if rSanitize.Data.MaliciousFile { + fmt.Println("File IS malicious") + } else { + fmt.Println("File is NOT malicious") + } + +} diff --git a/examples/sanitize/sanitize_split_upload_put_url.go b/examples/sanitize/sanitize_split_upload_put_url.go new file mode 100644 index 00000000..ca32190b --- /dev/null +++ b/examples/sanitize/sanitize_split_upload_put_url.go @@ -0,0 +1,140 @@ +package main + +import ( + "context" + "fmt" + "log" + "os" + "time" + + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/pangea" + "github.com/pangeacyber/pangea-go/pangea-sdk/v4/service/sanitize" +) + +func main() { + // Set filePath to your own file + const filePath = "./testdata/ds11.pdf" + + // Load Pangea token from environment variables + token := os.Getenv("PANGEA_SANITIZE_TOKEN") + if token == "" { + log.Fatal("Unauthorized: No token present.") + } + + ctx, cancelFn := context.WithTimeout(context.Background(), 120*time.Second) + defer cancelFn() + + // Create a new Sanitize client with Pangea token and domain + client := sanitize.New(&pangea.Config{ + Token: token, + Domain: os.Getenv("PANGEA_DOMAIN"), + QueuedRetryEnabled: true, + PollResultTimeout: 120 * time.Second, + Retry: true, + RetryConfig: &pangea.RetryConfig{ + RetryMax: 4, + }, + }) + + // Create a SanitizeRequest to request an presigned upload url. + // In this case TransferMethod is set to TMputURL + input := &sanitize.SanitizeRequest{ + Content: &sanitize.SanitizeContent{ + URLIntel: pangea.Bool(true), + URLIntelProvider: "crowdstrike", + DomainIntel: pangea.Bool(true), + DomainIntelProvider: "crowdstrike", + Defang: pangea.Bool(true), + DefangThreshold: pangea.Int(20), + RemoveInteractive: pangea.Bool(true), + RemoveAttachments: pangea.Bool(true), + Redact: pangea.Bool(true), + }, + ShareOutput: &sanitize.SanitizeShareOutput{ + Enabled: pangea.Bool(true), + OutputFolder: "sdk_test/sanitize/", + }, + File: &sanitize.SanitizeFile{ + ScanProvider: "crowdstrike", + }, + UploadedFileName: "uploaded_file", + TransferRequest: pangea.TransferRequest{ + TransferMethod: pangea.TMputURL, + }, + } + + fmt.Println("Request upload URL...") + resp, err := client.RequestUploadURL(ctx, input) + if err != nil { + log.Fatalf("Failed to get upload URL. Unexpected error: %v", err.Error()) + } + + // Get presigned url + url := resp.AcceptedResult.PutURL + fmt.Printf("Got URL: %s\n", url) + + file, err := os.Open(filePath) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + fd := pangea.FileData{ + File: file, + Name: "someName", + } + + // Create an uploader + uploader := pangea.NewFileUploader() + + fmt.Println("Uploading file...") + // Upload the file to the returned upload URL. + // Need to set transfer method again to TMputURL + err = uploader.UploadFile(ctx, url, pangea.TMputURL, fd) + if err != nil { + log.Fatalf("unexpected error: %v", err) + } + + var sr *pangea.PangeaResponse[any] + i := 0 + maxRetry := 24 + + // Try to poll result + for i < maxRetry { + // Wait until result should be ready + time.Sleep(time.Duration(10 * time.Second)) + + fmt.Printf("Trying to poll result. Retry: %d\n", i) + sr, err = client.PollResultByID(ctx, *resp.RequestID, &sanitize.SanitizeResult{}) + if err == nil { + break + } + i++ + fmt.Println("Result is not ready yet. Retrying...") + } + + if i >= maxRetry { + log.Fatal("Failed to poll result. Max retry reached.") + } + + // After receiving the result, cast it before using it. + rSanitize := (*sr.Result).(*sanitize.SanitizeResult) + + fmt.Println("File Sanitized:") + if rSanitize.DestShareID != nil { + fmt.Printf("\tShare ID: %s\n", *rSanitize.DestShareID) + } + if rSanitize.DestURL != nil { + fmt.Printf("\tDest URL: %s\n", *rSanitize.DestURL) + } + + fmt.Printf("\tRedact data: %s\n", pangea.Stringify(rSanitize.Data.Redact)) + fmt.Printf("\tDefang data: %s\n", pangea.Stringify(rSanitize.Data.Defang)) + fmt.Printf("\tCDR data: %s\n", pangea.Stringify(rSanitize.Data.CDR)) + + if rSanitize.Data.MaliciousFile { + fmt.Println("File IS malicious") + } else { + fmt.Println("File is NOT malicious") + } + +} diff --git a/examples/sanitize/testdata/ds11.pdf b/examples/sanitize/testdata/ds11.pdf new file mode 100644 index 00000000..6bd49ed0 Binary files /dev/null and b/examples/sanitize/testdata/ds11.pdf differ diff --git a/examples/sanitize/testdata/testfile.pdf b/examples/sanitize/testdata/testfile.pdf new file mode 100644 index 00000000..26704774 Binary files /dev/null and b/examples/sanitize/testdata/testfile.pdf differ diff --git a/examples/share/folder_create_and_delete.go b/examples/share/folder_create_and_delete.go index a4daab1c..8ebb4705 100644 --- a/examples/share/folder_create_and_delete.go +++ b/examples/share/folder_create_and_delete.go @@ -15,7 +15,7 @@ func main() { var t = time.Now().Format("20060102_150405") var path = "/sdk_example/delete/" + t - // Load pangea token from environment variables + // Load Pangea token from environment variables token := os.Getenv("PANGEA_SHARE_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present.") diff --git a/examples/share/item_life_cycle.go b/examples/share/item_life_cycle.go index 560027e7..e2bdd937 100644 --- a/examples/share/item_life_cycle.go +++ b/examples/share/item_life_cycle.go @@ -17,7 +17,7 @@ func main() { const filePath = "./testdata/testfile.pdf" var folder = "/examples/files/" + t - // Load pangea token from environment variables + // Load Pangea token from environment variables token := os.Getenv("PANGEA_SHARE_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present.") diff --git a/examples/share/put_split_upload.go b/examples/share/put_split_upload.go index 4c3b2549..cefbeae7 100644 --- a/examples/share/put_split_upload.go +++ b/examples/share/put_split_upload.go @@ -16,7 +16,7 @@ func main() { var name = "file_name_" + t const filePath = "./testdata/testfile.pdf" - // Load pangea token from environment variables + // Load Pangea token from environment variables token := os.Getenv("PANGEA_SHARE_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present.") @@ -67,7 +67,7 @@ func main() { // Create an upload uploader := pangea.NewFileUploader() - // Upload the file to the url get previously + // Upload the file to the returned upload URL. // Need to set transfer method again to TMputURL err = uploader.UploadFile(ctx, url, pangea.TMputURL, fd) if err != nil { @@ -89,7 +89,7 @@ func main() { i++ } - // Once got the result, cast it to use it + // After receiving the result, cast it before using it. rPut := (*pr.Result).(*share.PutResult) fmt.Println("File uploaded:") diff --git a/examples/share/put_transfer_method_multipart.go b/examples/share/put_transfer_method_multipart.go index 9b8476a5..94d7aca1 100644 --- a/examples/share/put_transfer_method_multipart.go +++ b/examples/share/put_transfer_method_multipart.go @@ -16,7 +16,7 @@ func main() { var name = "file_name_" + t const filePath = "./testdata/testfile.pdf" - // Load pangea token from environment variables + // Load Pangea token from environment variables token := os.Getenv("PANGEA_SHARE_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present.") diff --git a/examples/share/put_transfer_method_post_url.go b/examples/share/put_transfer_method_post_url.go index fc14c02f..d726f3a3 100644 --- a/examples/share/put_transfer_method_post_url.go +++ b/examples/share/put_transfer_method_post_url.go @@ -16,7 +16,7 @@ func main() { var name = "file_name_" + t const filePath = "./testdata/testfile.pdf" - // Load pangea token from environment variables + // Load Pangea token from environment variables token := os.Getenv("PANGEA_SHARE_TOKEN") if token == "" { log.Fatal("Unauthorized: No token present.") diff --git a/go.work b/go.work index da5bdab0..8949815f 100644 --- a/go.work +++ b/go.work @@ -8,6 +8,7 @@ use ( ./examples/file_scan ./examples/intel ./examples/redact + ./examples/sanitize ./examples/share ./examples/vault ./pangea-sdk diff --git a/go.work.sum b/go.work.sum index 63d8decd..f1afbc7a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,6 +1,26 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/pangeacyber/pangea-go/pangea-sdk/v4 v4.1.0/go.mod h1:5XIW52PITcGiggsoSVoFstTlF/5cU51sywvBD5gB6pk= +github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=