Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/external/customtemplates/s3.go
2070 views
1
package customtemplates
2
3
import (
4
"context"
5
"os"
6
"path/filepath"
7
"strings"
8
9
"github.com/aws/aws-sdk-go-v2/aws"
10
"github.com/aws/aws-sdk-go-v2/config"
11
"github.com/aws/aws-sdk-go-v2/credentials"
12
"github.com/aws/aws-sdk-go-v2/feature/s3/manager"
13
"github.com/aws/aws-sdk-go-v2/service/s3"
14
"github.com/projectdiscovery/gologger"
15
nucleiConfig "github.com/projectdiscovery/nuclei/v3/pkg/catalog/config"
16
"github.com/projectdiscovery/nuclei/v3/pkg/types"
17
"github.com/projectdiscovery/utils/errkit"
18
stringsutil "github.com/projectdiscovery/utils/strings"
19
)
20
21
var _ Provider = &customTemplateS3Bucket{}
22
23
type customTemplateS3Bucket struct {
24
s3Client *s3.Client
25
bucketName string
26
prefix string
27
Location string
28
}
29
30
// Download retrieves all custom templates from s3 bucket
31
func (bk *customTemplateS3Bucket) Download(ctx context.Context) {
32
downloadPath := filepath.Join(nucleiConfig.DefaultConfig.CustomS3TemplatesDirectory, bk.bucketName)
33
34
s3Manager := manager.NewDownloader(bk.s3Client)
35
paginator := s3.NewListObjectsV2Paginator(bk.s3Client, &s3.ListObjectsV2Input{
36
Bucket: &bk.bucketName,
37
Prefix: &bk.prefix,
38
})
39
40
for paginator.HasMorePages() {
41
page, err := paginator.NextPage(context.TODO())
42
if err != nil {
43
gologger.Error().Msgf("error downloading s3 bucket %s %s", bk.bucketName, err)
44
return
45
}
46
for _, obj := range page.Contents {
47
if err := downloadToFile(s3Manager, downloadPath, bk.bucketName, aws.ToString(obj.Key)); err != nil {
48
gologger.Error().Msgf("error downloading s3 bucket %s %s", bk.bucketName, err)
49
return
50
}
51
}
52
}
53
gologger.Info().Msgf("AWS bucket %s was cloned successfully at %s", bk.bucketName, downloadPath)
54
}
55
56
// Update downloads custom templates from s3 bucket
57
func (bk *customTemplateS3Bucket) Update(ctx context.Context) {
58
bk.Download(ctx)
59
}
60
61
// NewS3Providers returns a new instances of a s3 providers for downloading custom templates
62
func NewS3Providers(options *types.Options) ([]*customTemplateS3Bucket, error) {
63
providers := []*customTemplateS3Bucket{}
64
if options.AwsBucketName != "" && !options.AwsTemplateDisableDownload {
65
s3c, err := getS3Client(context.TODO(), options.AwsAccessKey, options.AwsSecretKey, options.AwsRegion, options.AwsProfile)
66
if err != nil {
67
errx := errkit.FromError(err)
68
errx.Msgf("error downloading s3 bucket %s", options.AwsBucketName)
69
return nil, errx
70
}
71
ctBucket := &customTemplateS3Bucket{
72
bucketName: options.AwsBucketName,
73
s3Client: s3c,
74
}
75
if strings.Contains(options.AwsBucketName, "/") {
76
bPath := strings.SplitN(options.AwsBucketName, "/", 2)
77
ctBucket.bucketName = bPath[0]
78
ctBucket.prefix = bPath[1]
79
}
80
providers = append(providers, ctBucket)
81
}
82
return providers, nil
83
}
84
85
func downloadToFile(downloader *manager.Downloader, targetDirectory, bucket, key string) error {
86
// Create the directories in the path
87
file := filepath.Join(targetDirectory, key)
88
// If empty dir in s3
89
if stringsutil.HasSuffixI(key, "/") {
90
return os.MkdirAll(file, 0775)
91
}
92
if err := os.MkdirAll(filepath.Dir(file), 0775); err != nil {
93
return err
94
}
95
96
// Set up the local file
97
fd, err := os.Create(file)
98
if err != nil {
99
return err
100
}
101
defer func() {
102
_ = fd.Close()
103
}()
104
105
// Download the file using the AWS SDK for Go
106
_, err = downloader.Download(context.TODO(), fd, &s3.GetObjectInput{Bucket: &bucket, Key: &key})
107
108
return err
109
}
110
111
func getS3Client(ctx context.Context, accessKey string, secretKey string, region string, profile string) (*s3.Client, error) {
112
var cfg aws.Config
113
var err error
114
if profile != "" {
115
cfg, err = config.LoadDefaultConfig(ctx, config.WithSharedConfigProfile(profile))
116
if err != nil {
117
return nil, err
118
}
119
} else if accessKey != "" && secretKey != "" {
120
cfg, err = config.LoadDefaultConfig(ctx, config.WithCredentialsProvider(credentials.NewStaticCredentialsProvider(accessKey, secretKey, "")), config.WithRegion(region))
121
if err != nil {
122
return nil, err
123
}
124
} else {
125
cfg, err = config.LoadDefaultConfig(ctx)
126
if err != nil {
127
return nil, err
128
}
129
}
130
return s3.NewFromConfig(cfg), nil
131
}
132
133