diff --git a/README.md b/README.md index 2ac9b9c..39d67ca 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ -# Nuclear Pond +# Nuclear Pond V.2 +`We forked this project so we can continue with this great idea, I hope that together we can improve the code and make it available to everyone - @OFJAAAH` -Nuclear Pond is used to leverage [Nuclei](https://github.com/projectdiscovery/nuclei) in the cloud with unremarkable speed, flexibility, and [perform internet wide scans for far less than a cup of coffee](https://devsecopsdocs.com/blog/nuclear-pond/). +To install Nuclear Pond, you need to configure the backend [terraform module](https://github.com/DevSecOpsDocs/terraform-nuclear-pond). You can do this by running `terraform apply` or by leveraging [terragrunt](https://terragrunt.gruntwork.io/). + It leverages [AWS Lambda](https://aws.amazon.com/lambda/) as a backend to invoke Nuclei scans in parallel, choice of storing json findings in s3 to query with [AWS Athena](https://aws.amazon.com/athena/), and is easily one of the cheapest ways you can execute scans in the cloud. @@ -24,7 +26,8 @@ Think of Nuclear Pond as just a way for you to run Nuclei in the cloud. You can ## Setup & Installation -To install Nuclear Pond, you need to configure the backend [terraform module](https://github.com/DevSecOpsDocs/terraform-nuclear-pond). You can do this by running `terraform apply` or by leveraging [terragrunt](https://terragrunt.gruntwork.io/). +To install Nuclear Pond, you need to configure the backend [terraform module](https://github.com/KingOfBugbounty/terraform-nuclear-pond-OFJAAAH). You can do this by running `terraform apply` or by leveraging [terragrunt](https://terragrunt.gruntwork.io/). + ```bash $ go install github.com/DevSecOpsDocs/nuclearpond@latest diff --git a/oryxBuildBinary b/oryxBuildBinary new file mode 100644 index 0000000..42735d7 Binary files /dev/null and b/oryxBuildBinary differ diff --git a/pkg/cmd/cmd.go b/pkg/cmd/cmd.go index 4bb42ab..974430a 100644 --- a/pkg/cmd/cmd.go +++ b/pkg/cmd/cmd.go @@ -1,29 +1,29 @@ package cmd import ( - "fmt" - "log" - "os" + "fmt" + "log" + "os" - "github.com/DevSecOpsDocs/nuclearpond/pkg/core" - "github.com/DevSecOpsDocs/nuclearpond/pkg/helpers" - "github.com/DevSecOpsDocs/nuclearpond/pkg/server" + "github.com/DevSecOpsDocs/nuclearpond/pkg/core" + "github.com/DevSecOpsDocs/nuclearpond/pkg/helpers" + "github.com/DevSecOpsDocs/nuclearpond/pkg/server" - "github.com/common-nighthawk/go-figure" - "github.com/spf13/cobra" + "github.com/common-nighthawk/go-figure" + "github.com/spf13/cobra" ) var asciiBanner = figure.NewFigure("Nuclear Pond", "", true).String() var rootCmd = &cobra.Command{ - Use: "nuclearpond", - Short: "A CLI tool for Nuclear Pond to run nuclei in parallel", - Long: "Nuclear Pond invokes nuclei in parallel through invoking lambda functions, customizes command line flags, specifies output, and batches requests.", - Example: `nuclearpond run -t devsecopsdocs.com -a $(echo -ne "-t dns" | base64) -o cmd`, - Run: func(cmd *cobra.Command, args []string) { - fmt.Println(asciiBanner) - cmd.Help() - }, + Use: "nuclearpond", + Short: "A CLI tool for Nuclear Pond to run nuclei in parallel", + Long: "Nuclear Pond invokes nuclei in parallel through invoking lambda functions, customizes command line flags, specifies output, and batches requests.", + Example: `nuclearpond run -t devsecopsdocs.com -a $(echo -ne "-t dns" | base64) -o cmd`, + Run: func(cmd *cobra.Command, args []string) { + fmt.Println(asciiBanner) + cmd.Help() + }, } var silent bool @@ -37,107 +37,107 @@ var output string var threads int var runCmd = &cobra.Command{ - Use: "run", - Short: "Execute nuclei tasks", - Long: "Executes nuclei tasks in parallel by invoking lambda asynchronously", - Run: func(cmd *cobra.Command, args []string) { - if !silent { - fmt.Println(asciiBanner) - fmt.Println(" devsecopsdocs.com") - fmt.Println() - } - - // Nuclei args flag - if nucleiArgs == "" { - log.Fatal("Nuclei arguments are required") - os.Exit(1) - } - - // Targets flag - if targets == "" && target == "" { - log.Fatal("Either a target or a list of targets is required") - os.Exit(1) - } - - if targets != "" { - urls := helpers.ReadUrlsFromFile(targets) - urls = helpers.RemoveEmpty(urls) - log.Println("Running nuclear pond against", len(urls), "targets") - batches := helpers.SplitSlice(urls, batchSize) - log.Println("Splitting targets into", len(batches), "individual executions") - log.Println("Running with " + fmt.Sprint(threads) + " threads") - core.ExecuteScans(batches, output, functionName, nucleiArgs, threads, silent) - } else { - log.Println("Running nuclei against the target", target) - log.Println("Running with " + fmt.Sprint(threads) + " threads") - batches := [][]string{{target}} - core.ExecuteScans(batches, output, functionName, nucleiArgs, threads, silent) - } - }, + Use: "run", + Short: "Execute nuclei tasks", + Long: "Executes nuclei tasks in parallel by invoking lambda asynchronously", + Run: func(cmd *cobra.Command, args []string) { + if !silent { + fmt.Println(asciiBanner) + fmt.Println(" devsecopsdocs.com") + fmt.Println() + } + + if nucleiArgs == "" { + log.Fatal("Nuclei arguments are required") + os.Exit(1) + } + + if targets == "" && target == "" { + log.Fatal("Either a target or a list of targets is required") + os.Exit(1) + } + + if targets != "" { + urls := helpers.ReadUrlsFromFile(targets) + urls = helpers.RemoveEmpty(urls) + log.Println("Running nuclear pond against", len(urls), "targets") + batches := helpers.SplitSlice(urls, batchSize) + log.Println("Splitting targets into", len(batches), "individual executions") + log.Println("Running with " + fmt.Sprint(threads) + " threads") + core.ExecuteScans(batches, output, functionName, nucleiArgs, threads, silent, region) + } else { + log.Println("Running nuclei against the target", target) + log.Println("Running with " + fmt.Sprint(threads) + " threads") + batches := [][]string{{target}} + core.ExecuteScans(batches, output, functionName, nucleiArgs, threads, silent, region) + } + }, } var startServer = &cobra.Command{ - Use: "service", - Short: "Launch API to launch run tasks to the nuclei runner.", - Long: "Executes nuclei through an API through asynchronous lambda functions", - Run: func(cmd *cobra.Command, args []string) { - // Print banner - fmt.Println(asciiBanner) - fmt.Println(" devsecopsdocs.com") - fmt.Println() - // Start server - log.Println("Running nuclear pond http server on port 8080") - log.Println("http://localhost:8080") - server.HandleRequests() - }, + Use: "service", + Short: "Launch API to launch run tasks to the nuclei runner.", + Long: "Executes nuclei through an API through asynchronous lambda functions", + Run: func(cmd *cobra.Command, args []string) { + // Print banner + fmt.Println(asciiBanner) + fmt.Println(" devsecopsdocs.com") + fmt.Println() + // Start server + log.Println("Running nuclear pond http server on port 8080") + log.Println("http://localhost:8080") + server.HandleRequests() + }, } func init() { - // run subcommand - // Mark flags as required - runCmd.MarkFlagRequired("args") - runCmd.MarkFlagRequired("output") - // General flags - runCmd.Flags().BoolVarP(&silent, "silent", "s", false, "silent command line output") - runCmd.Flags().StringVarP(&target, "target", "t", "", "individual target to specify") - runCmd.Flags().StringVarP(&targets, "targets", "l", "", "list of targets in a file") - runCmd.Flags().StringVarP(&nucleiArgs, "args", "a", "", "nuclei arguments as base64 encoded string") - runCmd.Flags().IntVarP(&batchSize, "batch-size", "b", 1, "batch size for number of targets per execution") - runCmd.Flags().StringVarP(&output, "output", "o", "cmd", "output type to save nuclei results(s3, cmd, or json)") - runCmd.Flags().IntVarP(&threads, "threads", "c", 1, "number of threads to run lambda functions, default is 1 which will be slow") - // Region flag - runCmd.Flags().StringVarP(®ion, "region", "r", "", "AWS region to run nuclei") - if region == "" { - region, ok := os.LookupEnv("AWS_REGION") - if !ok { - runCmd.MarkFlagRequired("region") - } else { - runCmd.Flags().Set("region", region) - } - } - // Function name flag - runCmd.Flags().StringVarP(&functionName, "function-name", "f", "", "AWS Lambda function name") - if functionName == "" { - functionName, ok := os.LookupEnv("AWS_LAMBDA_FUNCTION_NAME") - if !ok { - runCmd.MarkFlagRequired("function-name") - } else { - runCmd.Flags().Set("function-name", functionName) - } - } + // run subcommand + // Mark flags as required + runCmd.MarkFlagRequired("args") + runCmd.MarkFlagRequired("output") + // General flags + runCmd.Flags().BoolVarP(&silent, "silent", "s", false, "silent command line output") + runCmd.Flags().StringVarP(&target, "target", "t", "", "individual target to specify") + runCmd.Flags().StringVarP(&targets, "targets", "l", "", "list of targets in a file") + runCmd.Flags().StringVarP(&nucleiArgs, "args", "a", "", "nuclei arguments as base64 encoded string") + runCmd.Flags().IntVarP(&batchSize, "batch-size", "b", 1, "batch size for number of targets per execution") + runCmd.Flags().StringVarP(&output, "output", "o", "cmd", "output type to save nuclei results(s3, cmd, or json)") + runCmd.Flags().IntVarP(&threads, "threads", "c", 1, "number of threads to run lambda functions, default is 1 which will be slow") + // Region flag + runCmd.Flags().StringVarP(®ion, "region", "r", "", "AWS region to run nuclei") + if region == "" { + var ok bool // Declare ok here to avoid shadowing + region, ok = os.LookupEnv("AWS_REGION") // Removed := to modify the existing region variable + if !ok { + runCmd.MarkFlagRequired("region") + } else { + runCmd.Flags().Set("region", region) + } + } + + // Function name flag + runCmd.Flags().StringVarP(&functionName, "function-name", "f", "", "AWS Lambda function name") + if functionName == "" { + functionName, ok := os.LookupEnv("AWS_LAMBDA_FUNCTION_NAME") + if !ok { + runCmd.MarkFlagRequired("function-name") + } else { + runCmd.Flags().Set("function-name", functionName) + } + } } // Execute executes the root command. func Execute() error { - rootCmd.CompletionOptions.DisableDefaultCmd = true - rootCmd.SetHelpCommand(&cobra.Command{ - Use: "no-help", - Hidden: true, - }) + rootCmd.CompletionOptions.DisableDefaultCmd = true + rootCmd.SetHelpCommand(&cobra.Command{ + Use: "no-help", + Hidden: true, + }) - rootCmd.HasHelpSubCommands() - rootCmd.AddCommand(runCmd) - rootCmd.AddCommand(startServer) + rootCmd.HasHelpSubCommands() + rootCmd.AddCommand(runCmd) + rootCmd.AddCommand(startServer) - return rootCmd.Execute() + return rootCmd.Execute() } diff --git a/pkg/core/core.go b/pkg/core/core.go index 3de16e4..cdbc73a 100644 --- a/pkg/core/core.go +++ b/pkg/core/core.go @@ -1,61 +1,61 @@ package core import ( - "encoding/base64" - "log" - "strings" - "sync" - "time" + "encoding/base64" + "log" + "strings" + "sync" + "time" - "github.com/DevSecOpsDocs/nuclearpond/pkg/lambda" + "github.com/DevSecOpsDocs/nuclearpond/pkg/lambda" ) -func ExecuteScans(batches [][]string, output string, lambdaName string, nucleiArgs string, threads int, silent bool) { - // Get start time - start := time.Now() - - // Create a WaitGroup to wait for the goroutines to finish - var wg sync.WaitGroup - - // Set the number of threads to use - numThreads := threads - - // Create a channel to pass tasks to the goroutines - tasks := make(chan func()) - - // Start the goroutines - for i := 0; i < numThreads; i++ { - wg.Add(1) - go func() { - defer wg.Done() - for task := range tasks { - task() - } - }() - } - - // Add tasks to the channel - for _, batch := range batches { - decodedBytes, _ := base64.StdEncoding.DecodeString(nucleiArgs) - // Convert args.NucleiArg from base64, to string, split by space, and convert to list - nucleiFlags := strings.Split(string(decodedBytes), " ") - - // create lambda invoke struct - lambdaInvoke := lambda.LambdaInvoke{ - Targets: batch, - Args: nucleiFlags, - Output: output, - } - tasks <- func() { - lambda.InvokeLambdas(lambdaInvoke, lambdaName, output) - } - } - - close(tasks) - wg.Wait() - - // Print the results if not silent mode - if !silent { - log.Println("Completed all parallel operations, best of luck! Completed in", time.Since(start)) - } +func ExecuteScans(batches [][]string, output string, lambdaName string, nucleiArgs string, threads int, silent bool, region string) { + // Get start time + start := time.Now() + + // Create a WaitGroup to wait for the goroutines to finish + var wg sync.WaitGroup + + // Set the number of threads to use + numThreads := threads + + // Create a channel to pass tasks to the goroutines + tasks := make(chan func()) + + // Start the goroutines + for i := 0; i < numThreads; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for task := range tasks { + task() + } + }() + } + + // Add tasks to the channel + for _, batch := range batches { + decodedBytes, _ := base64.StdEncoding.DecodeString(nucleiArgs) + // Convert args.NucleiArg from base64, to string, split by space, and convert to list + nucleiFlags := strings.Split(string(decodedBytes), " ") + + // create lambda invoke struct + lambdaInvoke := lambda.LambdaInvoke{ + Targets: batch, + Args: nucleiFlags, + Output: output, + } + tasks <- func() { + lambda.InvokeLambdas(lambdaInvoke, lambdaName, output, region) + } + } + + close(tasks) + wg.Wait() + + // Print the results if not silent mode + if !silent { + log.Println("Completed all parallel operations, best of luck! Completed in", time.Since(start)) + } } diff --git a/pkg/lambda/lambda.go b/pkg/lambda/lambda.go index b7b032a..1e971cd 100644 --- a/pkg/lambda/lambda.go +++ b/pkg/lambda/lambda.go @@ -1,83 +1,82 @@ package lambda import ( - "encoding/json" - "fmt" - "log" - "os" + "encoding/json" + "fmt" + "log" + "os" - "github.com/DevSecOpsDocs/nuclearpond/pkg/outputs" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/lambda" + "github.com/DevSecOpsDocs/nuclearpond/pkg/outputs" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/lambda" ) -// struct for lambda invoke +// LambdaInvoke estrutura para invocar a função lambda. type LambdaInvoke struct { - Targets []string `json:"Targets"` - Args []string `json:"Args"` - Output string `json:"Output"` + Targets []string `json:"Targets"` + Args []string `json:"Args"` + Output string `json:"Output"` } -// Stage the lambda function for executing -func InvokeLambdas(payload LambdaInvoke, lambda string, output string) { - // Bug to fix another day - if payload.Targets[0] == "" { - return - } +// InvokeLambdas prepara e executa a função lambda. +func InvokeLambdas(payload LambdaInvoke, lambdaFunction string, output string, region string) { + if len(payload.Targets) == 0 { + return + } - // convert lambdaInvoke to json string - lambdaInvokeJson, err := json.Marshal(payload) - if err != nil { - log.Fatal(err) - } + lambdaInvokeJson, err := json.Marshal(payload) + if err != nil { + log.Fatal(err) + } - // invoke lambda function - response, err := invokeFunction(string(lambdaInvokeJson), lambda) - if err != nil { - fmt.Println(err) - } + response, err := invokeFunction(string(lambdaInvokeJson), lambdaFunction, region) + if err != nil { + log.Println("Erro ao invocar a função lambda:", err) + return + } - // Parse lambda response Output - var responseInterface interface{} - json.Unmarshal([]byte(response), &responseInterface) - // print responseInterface output value - lambdaResponse := responseInterface.(map[string]interface{})["output"] + var responseInterface map[string]interface{} + err = json.Unmarshal([]byte(response), &responseInterface) + if err != nil { + log.Println("Erro ao deserializar a resposta da função lambda:", err) + return + } - // Change outputs depending on the output - switch output { - case "s3": - outputs.S3Output(lambdaResponse) - case "cmd": - outputs.CmdOutput(lambdaResponse) - case "json": - outputs.JsonOutput(lambdaResponse) - } + lambdaResponse, exists := responseInterface["output"] + if !exists { + log.Println("Chave 'output' não encontrada na resposta da função lambda") + return + } + + switch output { + case "s3": + outputs.S3Output(lambdaResponse) + case "cmd": + outputs.CmdOutput(lambdaResponse) + case "json": + outputs.JsonOutput(lambdaResponse) + } } -// Execute a lambda function and return the response -func invokeFunction(payload string, functionName string) (string, error) { - // Create a new session - sess, err := session.NewSession(&aws.Config{ - Region: aws.String("us-east-1")}, - ) +// invokeFunction executa uma função lambda e retorna a resposta. +func invokeFunction(payload string, functionName string, region string) (string, error) { + sess, err := session.NewSession(&aws.Config{Region: aws.String(region)}) + if err != nil { + return "", fmt.Errorf("Erro ao criar sessão AWS: %v", err) + } - // Create a Lambda service client. - svc := lambda.New(sess) + svc := lambda.New(sess) - // Create the input - input := &lambda.InvokeInput{ - FunctionName: aws.String(functionName), - Payload: []byte(payload), - } + input := &lambda.InvokeInput{ + FunctionName: aws.String(functionName), + Payload: []byte(payload), + } - // Invoke the lambda function - result, err := svc.Invoke(input) - if err != nil { - log.Fatal("Failed to invoke lambda function: ", err) - os.Exit(1) - } + result, err := svc.Invoke(input) + if err != nil { + return "", fmt.Errorf("Erro ao invocar função lambda: %v", err) + } - // Return the response - return string(result.Payload), nil + return string(result.Payload), nil } diff --git a/pkg/server/scanner.go b/pkg/server/scanner.go index 55506a6..f92dd5e 100644 --- a/pkg/server/scanner.go +++ b/pkg/server/scanner.go @@ -1,110 +1,109 @@ package server import ( - "encoding/base64" - "fmt" - "log" - "os" - "strings" - "time" + "encoding/base64" + "fmt" + "log" + "os" + "strings" + "time" - "github.com/DevSecOpsDocs/nuclearpond/pkg/core" - "github.com/DevSecOpsDocs/nuclearpond/pkg/helpers" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/dynamodb" + "github.com/DevSecOpsDocs/nuclearpond/pkg/core" + "github.com/DevSecOpsDocs/nuclearpond/pkg/helpers" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/dynamodb" ) func backgroundScan(scanInput Request, scanId string) { - targets := helpers.RemoveEmpty(scanInput.Targets) - batches := helpers.SplitSlice(targets, scanInput.Batches) - output := scanInput.Output - threads := scanInput.Threads - NucleiArgs := base64.StdEncoding.EncodeToString([]byte(scanInput.Args)) - silent := true + targets := helpers.RemoveEmpty(scanInput.Targets) + batches := helpers.SplitSlice(targets, scanInput.Batches) + output := scanInput.Output + threads := scanInput.Threads + NucleiArgs := base64.StdEncoding.EncodeToString([]byte(scanInput.Args)) + silent := true - // Fail if AWS_LAMBDA_FUNCTION_NAME and AWS_REGION are not set - functionName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") - regionName := os.Getenv("AWS_REGION") - dynamodbTable := os.Getenv("AWS_DYNAMODB_TABLE") - if functionName == "" || regionName == "" || dynamodbTable == "" { - log.Fatal("AWS_LAMBDA_FUNCTION_NAME is not set") - } + functionName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") + regionName := os.Getenv("AWS_REGION") + dynamodbTable := os.Getenv("AWS_DYNAMODB_TABLE") - // Convert scanId to a valid DynamoDB key - requestId := strings.ReplaceAll(scanId, "-", "") + if functionName == "" || regionName == "" || dynamodbTable == "" { + log.Fatal("Environment variables (AWS_LAMBDA_FUNCTION_NAME, AWS_REGION, AWS_DYNAMODB_TABLE) are not set.") + } - log.Println("Initiating scan with the id of ", scanId, "with", len(targets), "targets") - storeScanState(requestId, "running") - core.ExecuteScans(batches, output, functionName, NucleiArgs, threads, silent) - storeScanState(requestId, "completed") - log.Println("Scan", scanId, "completed") + requestId := strings.ReplaceAll(scanId, "-", "") + + log.Println("Initiating scan with the id of ", scanId, "with", len(targets), "targets") + storeScanState(requestId, "running") + core.ExecuteScans(batches, output, functionName, NucleiArgs, threads, silent, regionName) + storeScanState(requestId, "completed") + log.Println("Scan", scanId, "completed") } func storeScanState(requestId string, status string) error { - log.Println("Stored scan state in Dynamodb", requestId, "as", status) + log.Println("Stored scan state in Dynamodb", requestId, "as", status) - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(os.Getenv("AWS_REGION")), - }) - if err != nil { - return err - } - // Create DynamoDB client - svc := dynamodb.New(sess) - // Prepare the item to be put into the DynamoDB table - item := &dynamodb.PutItemInput{ - TableName: aws.String(os.Getenv("AWS_DYNAMODB_TABLE")), - Item: map[string]*dynamodb.AttributeValue{ - "scan_id": { - S: aws.String(requestId), - }, - "status": { - S: aws.String(status), - }, - "timestamp": { - N: aws.String(fmt.Sprintf("%d", time.Now().Unix())), - }, - "ttl": { - N: aws.String(fmt.Sprintf("%d", time.Now().Add(time.Duration(30*time.Minute)).Unix())), - }, - }, - } - // Store the item in DynamoDB - _, err = svc.PutItem(item) - if err != nil { - log.Println("Failed to store scan state in Dynamodb:", err) - return err - } + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("AWS_REGION")), + }) + if err != nil { + return err + } + // Create DynamoDB client + svc := dynamodb.New(sess) + // Prepare the item to be put into the DynamoDB table + item := &dynamodb.PutItemInput{ + TableName: aws.String(os.Getenv("AWS_DYNAMODB_TABLE")), + Item: map[string]*dynamodb.AttributeValue{ + "scan_id": { + S: aws.String(requestId), + }, + "status": { + S: aws.String(status), + }, + "timestamp": { + N: aws.String(fmt.Sprintf("%d", time.Now().Unix())), + }, + "ttl": { + N: aws.String(fmt.Sprintf("%d", time.Now().Add(time.Duration(30*time.Minute)).Unix())), + }, + }, + } + // Store the item in DynamoDB + _, err = svc.PutItem(item) + if err != nil { + log.Println("Failed to store scan state in Dynamodb:", err) + return err + } - return nil + return nil } // function to retrieve the scan state from DynamoDB func getScanState(requestId string) (string, error) { - log.Println("Retrieving scan state from Dynamodb", requestId) + log.Println("Retrieving scan state from Dynamodb", requestId) - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(os.Getenv("AWS_REGION")), - }) - if err != nil { - return "failed", err - } - // Create DynamoDB client - svc := dynamodb.New(sess) - // Prepare the item to be put into the DynamoDB table - item := &dynamodb.GetItemInput{ - TableName: aws.String(os.Getenv("AWS_DYNAMODB_TABLE")), - Key: map[string]*dynamodb.AttributeValue{ - "scan_id": { - S: aws.String(requestId), - }, - }, - } - // Store the item in DynamoDB - result, err := svc.GetItem(item) - if err != nil { - return "failed", err - } - return *result.Item["status"].S, nil + sess, err := session.NewSession(&aws.Config{ + Region: aws.String(os.Getenv("AWS_REGION")), + }) + if err != nil { + return "failed", err + } + // Create DynamoDB client + svc := dynamodb.New(sess) + // Prepare the item to be put into the DynamoDB table + item := &dynamodb.GetItemInput{ + TableName: aws.String(os.Getenv("AWS_DYNAMODB_TABLE")), + Key: map[string]*dynamodb.AttributeValue{ + "scan_id": { + S: aws.String(requestId), + }, + }, + } + // Store the item in DynamoDB + result, err := svc.GetItem(item) + if err != nil { + return "failed", err + } + return *result.Item["status"].S, nil }