nuclei/v2/internal/runner/options.go

349 lines
12 KiB
Go
Raw Normal View History

2020-04-04 03:45:39 +05:30
package runner
import (
"bufio"
"fmt"
2020-04-04 03:45:39 +05:30
"os"
2021-08-27 17:06:06 +03:00
"path/filepath"
"strings"
2020-04-04 03:45:39 +05:30
"github.com/pkg/errors"
"github.com/go-playground/validator/v10"
"github.com/projectdiscovery/goflags"
2020-04-04 03:45:39 +05:30
"github.com/projectdiscovery/gologger"
"github.com/projectdiscovery/gologger/formatter"
"github.com/projectdiscovery/gologger/levels"
"github.com/projectdiscovery/nuclei/v2/pkg/catalog/config"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/protocolinit"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/common/utils/vardump"
"github.com/projectdiscovery/nuclei/v2/pkg/protocols/headless/engine"
"github.com/projectdiscovery/nuclei/v2/pkg/types"
fileutil "github.com/projectdiscovery/utils/file"
logutil "github.com/projectdiscovery/utils/log"
stringsutil "github.com/projectdiscovery/utils/strings"
2020-04-04 03:45:39 +05:30
)
func ConfigureOptions() error {
// with FileStringSliceOptions, FileNormalizedStringSliceOptions, FileCommaSeparatedStringSliceOptions
// if file has extension `.yaml,.json` we consider those as strings and not files to be read
isFromFileFunc := func(s string) bool {
return !config.IsTemplate(s)
}
2022-08-27 19:35:17 +05:30
goflags.FileNormalizedStringSliceOptions.IsFromFile = isFromFileFunc
goflags.FileStringSliceOptions.IsFromFile = isFromFileFunc
goflags.FileCommaSeparatedStringSliceOptions.IsFromFile = isFromFileFunc
return nil
}
2020-04-04 03:45:39 +05:30
// ParseOptions parses the command line flags provided by a user
func ParseOptions(options *types.Options) {
2020-04-04 03:45:39 +05:30
// Check if stdin pipe was given
options.Stdin = !options.DisableStdin && fileutil.HasStdin()
2020-04-04 03:45:39 +05:30
// Read the inputs from env variables that not passed by flag.
readEnvInputVars(options)
2020-04-04 03:45:39 +05:30
// Read the inputs and configure the logging
configureOutput(options)
2020-04-04 03:45:39 +05:30
// Show the user the banner
showBanner()
if options.ShowVarDump {
vardump.EnableVarDump = true
}
if options.ShowActions {
gologger.Info().Msgf("Showing available headless actions: ")
for action := range engine.ActionStringToAction {
gologger.Print().Msgf("\t%s", action)
}
os.Exit(0)
}
if options.StoreResponseDir != DefaultDumpTrafficOutputFolder && !options.StoreResponse {
gologger.Debug().Msgf("Store response directory specified, enabling \"store-resp\" flag automatically\n")
options.StoreResponse = true
}
2020-04-04 03:45:39 +05:30
// Validate the options passed by the user and if any
// invalid options have been used, exit.
if err := validateOptions(options); err != nil {
gologger.Fatal().Msgf("Program exiting: %s\n", err)
2020-04-04 03:45:39 +05:30
}
// Load the resolvers if user asked for them
loadResolvers(options)
err := protocolinit.Init(options)
if err != nil {
gologger.Fatal().Msgf("Could not initialize protocols: %s\n", err)
}
// Set Github token in env variable. runner.getGHClientWithToken() reads token from env
if options.GithubToken != "" && os.Getenv("GITHUB_TOKEN") != options.GithubToken {
os.Setenv("GITHUB_TOKEN", options.GithubToken)
}
if options.UncoverQuery != nil {
options.Uncover = true
if len(options.UncoverEngine) == 0 {
options.UncoverEngine = append(options.UncoverEngine, "shodan")
}
}
2020-04-04 03:45:39 +05:30
}
2020-08-29 15:26:11 +02:00
// validateOptions validates the configuration options passed
func validateOptions(options *types.Options) error {
validate := validator.New()
if err := validate.Struct(options); err != nil {
if _, ok := err.(*validator.InvalidValidationError); ok {
return err
}
errs := []string{}
for _, err := range err.(validator.ValidationErrors) {
errs = append(errs, err.Namespace()+": "+err.Tag())
}
return errors.Wrap(errors.New(strings.Join(errs, ", ")), "validation failed for these fields")
}
2020-08-29 15:26:11 +02:00
if options.Verbose && options.Silent {
return errors.New("both verbose and silent mode specified")
}
if options.FollowHostRedirects && options.FollowRedirects {
return errors.New("both follow host redirects and follow redirects specified")
}
if options.ShouldFollowHTTPRedirects() && options.DisableRedirects {
2022-04-27 11:19:44 -05:00
return errors.New("both follow redirects and disable redirects specified")
}
// loading the proxy server list from file or cli and test the connectivity
if err := loadProxyServers(options); err != nil {
2020-08-29 16:25:30 +02:00
return err
}
2021-08-27 17:06:06 +03:00
if options.Validate {
validateTemplatePaths(config.DefaultConfig.TemplatesDirectory, options.Templates, options.Workflows)
2021-08-27 17:06:06 +03:00
}
// Verify if any of the client certificate options were set since it requires all three to work properly
if len(options.ClientCertFile) > 0 || len(options.ClientKeyFile) > 0 || len(options.ClientCAFile) > 0 {
if len(options.ClientCertFile) == 0 || len(options.ClientKeyFile) == 0 || len(options.ClientCAFile) == 0 {
return errors.New("if a client certification option is provided, then all three must be provided")
}
validateCertificatePaths([]string{options.ClientCertFile, options.ClientKeyFile, options.ClientCAFile})
}
// Verify aws secrets are passed if s3 template bucket passed
if options.AwsBucketName != "" && options.UpdateTemplates {
cloud templates targets sync (#2959) * Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
2022-12-21 22:48:43 +05:30
missing := validateMissingS3Options(options)
if missing != nil {
return fmt.Errorf("aws s3 bucket details are missing. Please provide %s", strings.Join(missing, ","))
}
}
// Verify Azure connection configuration is passed if the Azure template bucket is passed
if options.AzureContainerName != "" && options.UpdateTemplates {
missing := validateMissingAzureOptions(options)
if missing != nil {
return fmt.Errorf("azure connection details are missing. Please provide %s", strings.Join(missing, ","))
}
}
// verify that a valid ip version type was selected (4, 6)
if len(options.IPVersion) == 0 {
// add ipv4 as default
options.IPVersion = append(options.IPVersion, "4")
}
var useIPV4, useIPV6 bool
for _, ipv := range options.IPVersion {
switch ipv {
case "4":
useIPV4 = true
case "6":
useIPV6 = true
default:
return fmt.Errorf("unsupported ip version: %s", ipv)
}
}
if !useIPV4 && !useIPV6 {
return errors.New("ipv4 and/or ipv6 must be selected")
}
cloud templates targets sync (#2959) * Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
2022-12-21 22:48:43 +05:30
// Validate cloud option
if err := validateCloudOptions(options); err != nil {
return err
}
return nil
}
func validateCloudOptions(options *types.Options) error {
if options.HasCloudOptions() && !options.Cloud {
return errors.New("cloud flags cannot be used without cloud option")
}
if options.Cloud {
if options.CloudAPIKey == "" {
return errors.New("missing NUCLEI_CLOUD_API env variable")
}
var missing []string
switch options.AddDatasource {
case "s3":
missing = validateMissingS3Options(options)
case "github":
missing = validateMissingGithubOptions(options)
case "azure":
missing = validateMissingAzureOptions(options)
cloud templates targets sync (#2959) * Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
2022-12-21 22:48:43 +05:30
}
if len(missing) > 0 {
return fmt.Errorf("missing %v env variables", strings.Join(missing, ", "))
}
}
2020-08-29 16:25:30 +02:00
return nil
}
cloud templates targets sync (#2959) * Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
2022-12-21 22:48:43 +05:30
func validateMissingS3Options(options *types.Options) []string {
var missing []string
if options.AwsBucketName == "" {
missing = append(missing, "AWS_TEMPLATE_BUCKET")
}
if options.AwsAccessKey == "" {
missing = append(missing, "AWS_ACCESS_KEY")
}
if options.AwsSecretKey == "" {
missing = append(missing, "AWS_SECRET_KEY")
}
if options.AwsRegion == "" {
missing = append(missing, "AWS_REGION")
}
return missing
}
func validateMissingAzureOptions(options *types.Options) []string {
var missing []string
if options.AzureTenantID == "" {
missing = append(missing, "AZURE_TENANT_ID")
}
if options.AzureClientID == "" {
missing = append(missing, "AZURE_CLIENT_ID")
}
if options.AzureClientSecret == "" {
missing = append(missing, "AZURE_CLIENT_SECRET")
}
if options.AzureServiceURL == "" {
missing = append(missing, "AZURE_SERVICE_URL")
}
if options.AzureContainerName == "" {
missing = append(missing, "AZURE_CONTAINER_NAME")
}
return missing
}
cloud templates targets sync (#2959) * Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
2022-12-21 22:48:43 +05:30
func validateMissingGithubOptions(options *types.Options) []string {
var missing []string
if options.GithubToken == "" {
missing = append(missing, "GITHUB_TOKEN")
}
if len(options.GithubTemplateRepo) == 0 {
missing = append(missing, "GITHUB_TEMPLATE_REPO")
}
return missing
}
// configureOutput configures the output logging levels to be displayed on the screen
func configureOutput(options *types.Options) {
2020-08-29 15:26:11 +02:00
// If the user desires verbose output, show verbose output
2021-12-01 10:35:18 -06:00
if options.Verbose || options.Validate {
gologger.DefaultLogger.SetMaxLevel(levels.LevelVerbose)
}
if options.Debug || options.DebugRequests || options.DebugResponse {
gologger.DefaultLogger.SetMaxLevel(levels.LevelDebug)
2020-08-29 15:26:11 +02:00
}
if options.NoColor {
gologger.DefaultLogger.SetFormatter(formatter.NewCLI(true))
2020-08-29 15:26:11 +02:00
}
if options.Silent {
gologger.DefaultLogger.SetMaxLevel(levels.LevelSilent)
2020-08-29 15:26:11 +02:00
}
// disable standard logger (ref: https://github.com/golang/go/issues/19895)
logutil.DisableDefaultLogger()
2020-08-29 15:26:11 +02:00
}
// loadResolvers loads resolvers from both user provided flag and file
func loadResolvers(options *types.Options) {
if options.ResolversFile == "" {
return
}
file, err := os.Open(options.ResolversFile)
if err != nil {
gologger.Fatal().Msgf("Could not open resolvers file: %s\n", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
part := scanner.Text()
if part == "" {
continue
}
if strings.Contains(part, ":") {
options.InternalResolversList = append(options.InternalResolversList, part)
} else {
options.InternalResolversList = append(options.InternalResolversList, part+":53")
}
}
}
2021-08-27 17:06:06 +03:00
func validateTemplatePaths(templatesDirectory string, templatePaths, workflowPaths []string) {
allGivenTemplatePaths := append(templatePaths, workflowPaths...)
for _, templatePath := range allGivenTemplatePaths {
if templatesDirectory != templatePath && filepath.IsAbs(templatePath) {
fileInfo, err := os.Stat(templatePath)
if err == nil && fileInfo.IsDir() {
relativizedPath, err2 := filepath.Rel(templatesDirectory, templatePath)
if err2 != nil || (len(relativizedPath) >= 2 && relativizedPath[:2] == "..") {
gologger.Warning().Msgf("The given path (%s) is outside the default template directory path (%s)! "+
"Referenced sub-templates with relative paths in workflows will be resolved against the default template directory.", templatePath, templatesDirectory)
break
}
}
}
}
}
func validateCertificatePaths(certificatePaths []string) {
for _, certificatePath := range certificatePaths {
if _, err := os.Stat(certificatePath); os.IsNotExist(err) {
// The provided path to the PEM certificate does not exist for the client authentication. As this is
// required for successful authentication, log and return an error
gologger.Fatal().Msgf("The given path (%s) to the certificate does not exist!", certificatePath)
break
}
}
}
// Read the input from env and set options
func readEnvInputVars(options *types.Options) {
cloud templates targets sync (#2959) * Add s3 bucket template provider - Refactor the custom github template code - add interface for template provider * Validate if aws creds are passed if bucket flag - refactor s3 provider struct to take client - add function which returns the aws s3 client - update error messages * Add aws s3 bucket flags documentation in README.md - Rename the github_test.go to customTemplate_test.go * go mod update * Move template provider code to pkg/external/customtemplates dir * Added initial data_source sync to cloud * Misc * Add pagination to scan output and scan list (#2858) * Add pagination to scan output and scan list * Use time based parameters instead of page numbers * Fix linting errors * Do not check limits at client, check at server * Remove unused constant * Misc update * Removed unnecessary flags * Misc * Misc * Misc endpoint additions * Added more routes * Typo fix * Misc fixes * Misc * Misc fixes to cloud target logic + use int for IDs * Misc * Misc fixes * Misc * Misc fixes * readme update * Add JSON output support for list-scan option (#2876) * Add JSON output support for list-scan option * Fix typo in cloud JSON output description * Following changes - Update status(finished, running) to be lower-case by default - Convert status to upper-case in DisplayScanList() * Update status to be lower-case by default * Remove additional json flag, instead use existing * Merge conflict * Accomodate comment changes and restructure code Co-authored-by: Jaideep K <jaideep@one2n.in> * Use integer IDs for scan tasks * Added get-templates-targets endpoint + JSON + validation * Added target count list * misc option / description updates * Added changes as per code review * duplicate options + typo updates * Added tablewriter for tabular data writing by default * Fixed list scan endpoint * Review changes * workflow fix * Added cloud tags etc based filtering (#3070) * Added omitempty for filtering request * go mod tidy * misc format update Co-authored-by: shubhamrasal <shubhamdharmarasal@gmail.com> Co-authored-by: Ice3man <nizamulrana@gmail.com> Co-authored-by: Jaideep Khandelwal <jdk2588@gmail.com> Co-authored-by: Siddharth Shashikar <60960197+shashikarsiddharth@users.noreply.github.com> Co-authored-by: Jaideep K <jaideep@one2n.in>
2022-12-21 22:48:43 +05:30
if strings.EqualFold(os.Getenv("NUCLEI_CLOUD"), "true") {
options.Cloud = true
}
if options.CloudURL = os.Getenv("NUCLEI_CLOUD_SERVER"); options.CloudURL == "" {
options.CloudURL = "https://cloud-dev.nuclei.sh"
}
options.CloudAPIKey = os.Getenv("NUCLEI_CLOUD_API")
options.GithubToken = os.Getenv("GITHUB_TOKEN")
repolist := os.Getenv("GITHUB_TEMPLATE_REPO")
if repolist != "" {
options.GithubTemplateRepo = append(options.GithubTemplateRepo, stringsutil.SplitAny(repolist, ",")...)
}
// AWS options for downloading templates from an S3 bucket
options.AwsAccessKey = os.Getenv("AWS_ACCESS_KEY")
options.AwsSecretKey = os.Getenv("AWS_SECRET_KEY")
options.AwsBucketName = os.Getenv("AWS_TEMPLATE_BUCKET")
options.AwsRegion = os.Getenv("AWS_REGION")
// Azure options for downloading templates from an Azure Blob Storage container
options.AzureContainerName = os.Getenv("AZURE_CONTAINER_NAME")
options.AzureTenantID = os.Getenv("AZURE_TENANT_ID")
options.AzureClientID = os.Getenv("AZURE_CLIENT_ID")
options.AzureClientSecret = os.Getenv("AZURE_CLIENT_SECRET")
options.AzureServiceURL = os.Getenv("AZURE_SERVICE_URL")
}