Path: blob/dev/pkg/external/customtemplates/s3.go
2070 views
package customtemplates12import (3"context"4"os"5"path/filepath"6"strings"78"github.com/aws/aws-sdk-go-v2/aws"9"github.com/aws/aws-sdk-go-v2/config"10"github.com/aws/aws-sdk-go-v2/credentials"11"github.com/aws/aws-sdk-go-v2/feature/s3/manager"12"github.com/aws/aws-sdk-go-v2/service/s3"13"github.com/projectdiscovery/gologger"14nucleiConfig "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"15"github.com/projectdiscovery/nuclei/v3/pkg/types"16"github.com/projectdiscovery/utils/errkit"17stringsutil "github.com/projectdiscovery/utils/strings"18)1920var _ Provider = &customTemplateS3Bucket{}2122type customTemplateS3Bucket struct {23s3Client *s3.Client24bucketName string25prefix string26Location string27}2829// Download retrieves all custom templates from s3 bucket30func (bk *customTemplateS3Bucket) Download(ctx context.Context) {31downloadPath := filepath.Join(nucleiConfig.DefaultConfig.CustomS3TemplatesDirectory, bk.bucketName)3233s3Manager := manager.NewDownloader(bk.s3Client)34paginator := s3.NewListObjectsV2Paginator(bk.s3Client, &s3.ListObjectsV2Input{35Bucket: &bk.bucketName,36Prefix: &bk.prefix,37})3839for paginator.HasMorePages() {40page, err := paginator.NextPage(context.TODO())41if err != nil {42gologger.Error().Msgf("error downloading s3 bucket %s %s", bk.bucketName, err)43return44}45for _, obj := range page.Contents {46if err := downloadToFile(s3Manager, downloadPath, bk.bucketName, aws.ToString(obj.Key)); err != nil {47gologger.Error().Msgf("error downloading s3 bucket %s %s", bk.bucketName, err)48return49}50}51}52gologger.Info().Msgf("AWS bucket %s was cloned successfully at %s", bk.bucketName, downloadPath)53}5455// Update downloads custom templates from s3 bucket56func (bk *customTemplateS3Bucket) Update(ctx context.Context) {57bk.Download(ctx)58}5960// NewS3Providers returns a new instances of a s3 providers for downloading custom templates61func NewS3Providers(options *types.Options) ([]*customTemplateS3Bucket, error) {62providers := []*customTemplateS3Bucket{}63if options.AwsBucketName != "" && !options.AwsTemplateDisableDownload {64s3c, err := getS3Client(context.TODO(), options.AwsAccessKey, options.AwsSecretKey, options.AwsRegion, options.AwsProfile)65if err != nil {66errx := errkit.FromError(err)67errx.Msgf("error downloading s3 bucket %s", options.AwsBucketName)68return nil, errx69}70ctBucket := &customTemplateS3Bucket{71bucketName: options.AwsBucketName,72s3Client: s3c,73}74if strings.Contains(options.AwsBucketName, "/") {75bPath := strings.SplitN(options.AwsBucketName, "/", 2)76ctBucket.bucketName = bPath[0]77ctBucket.prefix = bPath[1]78}79providers = append(providers, ctBucket)80}81return providers, nil82}8384func downloadToFile(downloader *manager.Downloader, targetDirectory, bucket, key string) error {85// Create the directories in the path86file := filepath.Join(targetDirectory, key)87// If empty dir in s388if stringsutil.HasSuffixI(key, "/") {89return os.MkdirAll(file, 0775)90}91if err := os.MkdirAll(filepath.Dir(file), 0775); err != nil {92return err93}9495// Set up the local file96fd, err := os.Create(file)97if err != nil {98return err99}100defer func() {101_ = fd.Close()102}()103104// Download the file using the AWS SDK for Go105_, err = downloader.Download(context.TODO(), fd, &s3.GetObjectInput{Bucket: &bucket, Key: &key})106107return err108}109110func getS3Client(ctx context.Context, accessKey string, secretKey string, region string, profile string) (*s3.Client, error) {111var cfg aws.Config112var err error113if profile != "" {114cfg, err = config.LoadDefaultConfig(ctx, config.WithSharedConfigProfile(profile))115if err != nil {116return nil, err117}118} else if accessKey != "" && secretKey != "" {119cfg, err = config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")), config.WithRegion(region))120if err != nil {121return nil, err122}123} else {124cfg, err = config.LoadDefaultConfig(ctx)125if err != nil {126return nil, err127}128}129return s3.NewFromConfig(cfg), nil130}131132133