Projects STRLCPY Osmedeus Commits 738cc688
🤬
  • Release v4.3.0: Added AWS provider, new scripts to backup workspace to s3 bucket and improved report command

  • Loading...
  • j3ssie committed 1 year ago
    738cc688
    1 parent 945cb90f
  • ■ ■ ■ ■ ■ ■
    README.md
    skipped 66 lines
    67 67   
    68 68  # Practical Scan Usage:
    69 69   osmedeus scan -T list_of_targets.txt -W custom_workspaces
     70 + osmedeus scan -t target.com -w workspace_name --debug
     71 + osmedeus scan -f general -t sample.com
    70 72   osmedeus scan --tactic aggressive -f general -t sample.com
    71  - osmedeus scan -f general -t www.sample.com
     73 + osmedeus scan -f extensive -t sample.com -t another.com
     74 + cat list_of_urls.txt | osmedeus scan -f urls
     75 + osmedeus scan --threads-hold=30 -f cidr -t 1.2.3.4/24
    72 76   osmedeus scan -m ~/.osmedeus/core/workflow/test/dirbscan.yaml -t list_of_urls.txt
    73 77   osmedeus scan --wfFolder ~/custom-workflow/ -f your-custom-workflow -t list_of_urls.txt
     78 + osmedeus scan --chunk --chunk-part 40 -c 2 -f cidr -t list-of-cidr.txt
    74 79   
    75 80  # Queue Usage:
    76 81   osmedeus queue -Q /tmp/queue-file.txt -c 2
    77 82   osmedeus queue --add -t example.com -Q /tmp/queue-file.txt
    78 83   
    79 84  # Provider Usage:
    80  - osmedeus provider build
     85 + osmedeus provider wizard
     86 + osmedeus provider validate
    81 87   osmedeus provider build --token xxx --rebuild --ic
    82 88   osmedeus provider create --name 'sample'
    83 89   osmedeus provider health --debug
     90 + osmedeus provider list
     91 + osmedeus provider delete --id 34317111 --id 34317112
    84 92   
    85 93  # Cloud Usage:
    86 94   osmedeus cloud -f [flowName] -t [target]
    87 95   osmedeus cloud -m [modulePath] -t [target]
    88  - osmedeus cloud -c 10 -f [flowName] -T [targetsFile]
    89  - osmedeus cloud --token xxx -G -c 10 -f [flowName] -T [targetsFile]
    90  - osmedeus cloud --chunk -c 10 -f [flowName] -t [targetsFile]
     96 + osmedeus cloud -c 5 -f [flowName] -T [targetsFile]
     97 + osmedeus cloud --token xxx -c 5 -f [flowName] -T [targetsFile]
     98 + osmedeus cloud --chunk -c 5 -f [flowName] -t [targetsFile]
    91 99   
    92 100  # Utilities Usage:
    93 101   ## Health check utility
    skipped 38 lines
  • ■ ■ ■ ■ ■ ■
    cmd/provider.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "os"
     6 + "sync"
     7 + 
    5 8   "github.com/j3ssie/osmedeus/core"
    6 9   "github.com/j3ssie/osmedeus/distribute"
    7 10   "github.com/j3ssie/osmedeus/provider"
    skipped 1 lines
    9 12   "github.com/olekukonko/tablewriter"
    10 13   "github.com/panjf2000/ants"
    11 14   "github.com/spf13/cobra"
    12  - "os"
    13  - "sync"
    14 15  )
    15 16   
    16 17  func init() {
    17 18   var providerCmd = &cobra.Command{
    18  - Use: "provider",
    19  - Short: "Cloud utils for Distributed Mode",
    20  - Long: core.Banner(),
    21  - RunE: runProvider,
     19 + Use: "provider",
     20 + Aliases: []string{"provide", "pro"},
     21 + Short: "Cloud utils for Distributed Mode",
     22 + Long: core.Banner(),
     23 + RunE: runProvider,
    22 24   }
    23 25   
    24 26   providerCmd.PersistentFlags().StringVar(&options.Cloud.RawCommand, "cmd", "", "raw command")
    skipped 15 lines
    40 42   providerWizard.PersistentFlags().BoolVar(&options.Cloud.AddNewProvider, "add", false, "Open wizard to add new provider only")
    41 43   
    42 44   var providerBuild = &cobra.Command{
    43  - Use: "build",
    44  - Short: "Build snapshot image",
    45  - Long: core.Banner(),
    46  - RunE: runProviderBuild,
     45 + Use: "build",
     46 + Aliases: []string{"buil"},
     47 + Short: "Build snapshot image",
     48 + Long: core.Banner(),
     49 + RunE: runProviderBuild,
    47 50   }
    48 51   var providerCreate = &cobra.Command{
    49  - Use: "create",
    50  - Short: "Create cloud instance based on image",
    51  - Long: core.Banner(),
    52  - RunE: runProviderCreate,
     52 + Use: "create",
     53 + Aliases: []string{"cre"},
     54 + Short: "Create cloud instance based on image",
     55 + Long: core.Banner(),
     56 + RunE: runProviderCreate,
    53 57   }
    54 58   
    55 59   var providerHealth = &cobra.Command{
    56  - Use: "health",
    57  - Short: "Run a health check on running cloud instances",
    58  - Long: core.Banner(),
    59  - RunE: runCloudHealth,
     60 + Use: "health",
     61 + Aliases: []string{"heal"},
     62 + Short: "Run a health check on running cloud instances",
     63 + Long: core.Banner(),
     64 + RunE: runCloudHealth,
    60 65   }
    61 66   
    62 67   var providerValidate = &cobra.Command{
    63  - Use: "validate",
    64  - Short: "Run validate of the existing cloud configs",
    65  - Long: core.Banner(),
    66  - RunE: runProviderValidate,
     68 + Use: "validate",
     69 + Aliases: []string{"val"},
     70 + Short: "Run validate of the existing cloud configs",
     71 + Long: core.Banner(),
     72 + RunE: runProviderValidate,
    67 73   }
    68 74   var providerList = &cobra.Command{
    69 75   Use: "list",
    70 76   Aliases: []string{"ls"},
    71  - Short: "List all instances",
     77 + Short: "List all running instances",
    72 78   Long: core.Banner(),
    73 79   RunE: runProviderListing,
    74 80   }
    75 81   var providerDel = &cobra.Command{
    76 82   Use: "delete",
    77 83   Aliases: []string{"del"},
    78  - Short: "Delete instances",
     84 + Short: "Delete instances by id",
    79 85   Long: core.Banner(),
    80 86   RunE: runProviderDelete,
    81 87   }
    skipped 150 lines
  • ■ ■ ■ ■ ■ ■
    cmd/report.go
    1 1  package cmd
    2 2   
    3 3  import (
     4 + "io/ioutil"
     5 + "net/http"
     6 + "path"
     7 + "path/filepath"
     8 + "strings"
     9 + 
    4 10   "github.com/fatih/color"
    5 11   "github.com/j3ssie/osmedeus/core"
    6 12   "github.com/j3ssie/osmedeus/utils"
    7 13   "github.com/spf13/cobra"
    8  - "io/ioutil"
    9  - "net/http"
    10  - "path/filepath"
    11 14  )
    12 15   
    13 16  func init() {
    skipped 78 lines
    92 95   }
    93 96   }
    94 97   
    95  - for _, target := range options.Scan.Inputs {
    96  - core.ExtractBackup(target, options)
     98 + for _, input := range options.Scan.Inputs {
     99 + core.ExtractBackup(input, options)
     100 + 
     101 + target := strings.ReplaceAll(path.Base(input), ".tar.gz", "")
     102 + core.ListSingleWorkspace(options, target)
    97 103   }
    98 104   
    99 105   return nil
    skipped 31 lines
  • ■ ■ ■ ■ ■ ■
    cmd/scan.go
    1 1  package cmd
    2 2   
    3 3  import (
     4 + "strings"
     5 + "sync"
     6 + 
    4 7   "github.com/fatih/color"
    5 8   "github.com/j3ssie/osmedeus/core"
    6 9   "github.com/j3ssie/osmedeus/libs"
    skipped 2 lines
    9 12   "github.com/spf13/cobra"
    10 13   "golang.org/x/text/cases"
    11 14   "golang.org/x/text/language"
    12  - "strings"
    13  - "sync"
    14 15  )
    15 16   
    16 17  func init() {
    17 18   var scanCmd = &cobra.Command{
    18 19   Use: "scan",
    19  - Short: "Do Scan based on predefined flow",
     20 + Short: "Conduct a scan following a predetermined flow/module",
    20 21   Long: core.Banner(),
    21 22   RunE: runScan,
    22 23   }
    skipped 52 lines
  • ■ ■ ■ ■ ■ ■
    cmd/usage.go
    skipped 90 lines
    91 91   h += " osmedeus health git\n"
    92 92   h += " osmedeus health cloud\n"
    93 93   h += " osmedeus version --json \n"
     94 + 
     95 + h += color.HiBlackString(" ## Update utilities\n")
    94 96   h += " osmedeus update \n"
    95 97   h += " osmedeus update --vuln\n"
    96 98   h += " osmedeus update --force --clean \n"
     99 + 
     100 + h += color.HiBlackString(" ## Other utilities\n")
    97 101   h += " osmedeus utils tmux ls \n"
    98 102   h += " osmedeus utils tmux logs -A -l 10 \n"
    99 103   h += " osmedeus utils ps \n"
    skipped 46 lines
    146 150   h += color.HiCyanString("\nCloud Usage:\n")
    147 151   h += " osmedeus cloud -f [flowName] -t [target] \n"
    148 152   h += " osmedeus cloud -m [modulePath] -t [target] \n"
    149  - h += " osmedeus cloud -c 10 -f [flowName] -T [targetsFile] \n"
    150  - h += " osmedeus cloud --token xxx -G -c 10 -f [flowName] -T [targetsFile] \n"
    151  - h += " osmedeus cloud --chunk -c 10 -f [flowName] -t [targetsFile] \n"
     153 + h += " osmedeus cloud -c 5 -f [flowName] -T [targetsFile] \n"
     154 + h += " osmedeus cloud --token xxx -c 5 -f [flowName] -T [targetsFile] \n"
     155 + h += " osmedeus cloud --chunk -c 5 -f [flowName] -t [targetsFile] \n"
    152 156   
    153 157   return h
    154 158  }
    skipped 69 lines
  • ■ ■ ■ ■ ■ ■
    core/backup.go
    1 1  package core
    2 2   
    3 3  import (
     4 + "os"
     5 + "path"
     6 + "strings"
     7 + 
    4 8   "github.com/fatih/color"
    5 9   "github.com/j3ssie/osmedeus/execution"
    6 10   "github.com/j3ssie/osmedeus/libs"
    7 11   "github.com/j3ssie/osmedeus/utils"
    8  - "os"
    9  - "path"
    10  - "strings"
    11 12  )
     13 + 
     14 +// in workflow file
     15 +// Compress('{{Backup}}/{{Workspace}}.tar.gz', '{{Output}}')
     16 +// Decompress('{{Output}}', '{{Backup}}/{{Workspace}}.tar.gz')
    12 17   
    13 18  func (r *Runner) BackupWorkspace() {
    14 19   outputDir := r.Target["Output"]
    skipped 15 lines
    30 35   }
    31 36   
    32 37   target := strings.ReplaceAll(path.Base(src), ".tar.gz", "")
    33  - dest := opt.Report.ExtractFolder
     38 + dest := path.Join(opt.Report.ExtractFolder, target)
    34 39   if !strings.HasSuffix(dest, "/") {
    35 40   dest += "/"
    36 41   }
    skipped 8 lines
  • ■ ■ ■ ■ ■ ■
    core/config.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "os"
     6 + "path"
     7 + "path/filepath"
     8 + "runtime"
     9 + "strings"
     10 + 
    5 11   "github.com/fatih/color"
    6 12   "github.com/j3ssie/osmedeus/execution"
    7 13   "github.com/j3ssie/osmedeus/libs"
    skipped 1 lines
    9 15   "github.com/j3ssie/osmedeus/utils"
    10 16   "github.com/spf13/cast"
    11 17   "github.com/spf13/viper"
    12  - "os"
    13  - "path"
    14  - "path/filepath"
    15  - "runtime"
    16  - "strings"
    17 18  )
    18 19   
    19 20  var v *viper.Viper
    skipped 137 lines
    157 158   })
    158 159   
    159 160   v.SetDefault("Cdn", map[string]string{
    160  - // this is default s3 bucket for public report that generated by osmedeus
    161  - "public_s3_bucket": utils.GetOSEnv("PUBLIC_S3_BUCKET", "PUBLIC_S3_BUCKET"),
    162  - // this should be a private s3 bucket for private report that only own by you
    163  - "private_s3_bucket": utils.GetOSEnv("PRIVATE_S3_BUCKET", "PRIVATE_S3_BUCKET"),
    164  - "aws_access_key": utils.GetOSEnv("AWS_ACCESS_KEY", "AWS_ACCESS_KEY"),
    165  - "aws_secret_key": utils.GetOSEnv("AWS_SECRET_KEY", "AWS_SECRET_KEY"),
     161 + "cdn_s3_bucket": utils.GetOSEnv("CDN_S3_BUCKET", "CDN_S3_BUCKET"),
     162 + "cdn_aws_access_key": utils.GetOSEnv("CDN_AWS_ACCESS_KEY", "CDN_AWS_ACCESS_KEY"),
     163 + "cdn_aws_secret_key": utils.GetOSEnv("CDN_AWS_SECRET_KEY", "CDN_AWS_SECRET_KEY"),
     164 + "cdn_aws_region": utils.GetOSEnv("CDN_AWS_REGION", "ap-southeast-1"),
    166 165   })
    167 166   
    168 167   v.SetDefault("Tactic", map[string]any{
    skipped 45 lines
    214 213   GetRemote(options)
    215 214   GetGit(options)
    216 215   //GetSync(options)
    217  - //GetCdn(options)
     216 + GetCdn(options)
    218 217   SetupOpt(options)
    219 218   GetCloud(options)
    220 219  }
    skipped 257 lines
    478 477   cloudConfigFile := path.Join(options.Env.CloudConfigFolder, "provider.yaml")
    479 478   
    480 479   options.CloudConfigFile = cloudConfigFile
    481  - utils.DebugF("Parsing cloud config from: %s", options.CloudConfigFile)
     480 + utils.DebugF("Parsing cloud config from: %s", color.HiCyanString(options.CloudConfigFile))
    482 481   providerConfigs, err := provider.ParseProvider(options.CloudConfigFile)
    483 482   
    484 483   if err != nil {
    skipped 78 lines
    563 562   options.Remote.PoolCred = pool["cred"]
    564 563  }
    565 564   
     565 +// GetCdn get options for client
     566 +func GetCdn(options *libs.Options) {
     567 + cdn := v.GetStringMapString("Cdn")
     568 + options.Cdn.Bucket = cdn["cdn_s3_bucket"]
     569 + options.Cdn.AccessKeyId = cdn["cdn_aws_access_key"]
     570 + options.Cdn.SecretKey = cdn["cdn_aws_secret_key"]
     571 + options.Cdn.Region = cdn["cdn_aws_region"]
     572 +}
     573 + 
    566 574  // GetClient get options for client
    567 575  func GetClient(options *libs.Options) map[string]string {
    568 576   client := v.GetStringMapString("Client")
    skipped 40 lines
    609 617   utils.InforF("Reload Env to the config file: %v", options.ConfigFile)
    610 618   
    611 619   v.Set("Cdn", map[string]string{
    612  - // this is default s3 bucket for public report that generated by osmedeus
    613  - "public_s3_bucket": utils.GetOSEnv("PUBLIC_S3_BUCKET", "PUBLIC_S3_BUCKET"),
    614  - // this should be a private s3 bucket for private report that only own by you
    615  - "private_s3_bucket": utils.GetOSEnv("PRIVATE_S3_BUCKET", "PRIVATE_S3_BUCKET"),
    616  - "aws_access_key": utils.GetOSEnv("AWS_ACCESS_KEY", "AWS_ACCESS_KEY"),
    617  - "aws_secret_key": utils.GetOSEnv("AWS_SECRET_KEY", "AWS_SECRET_KEY"),
     620 + "cdn_s3_bucket": utils.GetOSEnv("CDN_S3_BUCKET", "CDN_S3_BUCKET"),
     621 + "cdn_aws_access_key": utils.GetOSEnv("CDN_AWS_ACCESS_KEY", "CDN_AWS_ACCESS_KEY"),
     622 + "cdn_aws_secret_key": utils.GetOSEnv("CDN_AWS_SECRET_KEY", "CDN_AWS_SECRET_KEY"),
     623 + "cdn_aws_region": utils.GetOSEnv("CDN_AWS_REGION", "ap-southeast-1"),
    618 624   })
    619 625   
    620 626   // things should be reloaded by env
    skipped 58 lines
  • ■ ■ ■ ■ ■
    core/external.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "path"
     6 + "time"
     7 + 
    5 8   "github.com/j3ssie/osmedeus/execution"
    6 9   "github.com/j3ssie/osmedeus/utils"
    7 10   "github.com/robertkrimen/otto"
    8  - "path"
    9  - "time"
    10 11  )
    11 12   
    12 13  func (r *Runner) LoadExternalScripts() string {
    skipped 176 lines
    189 190   return otto.Value{}
    190 191   })
    191 192   
    192  - vm.Set(GetFileFromCDN, func(call otto.FunctionCall) otto.Value {
     193 + /* --- CDN S3 Bucket --- */
     194 + 
     195 + // UploadToS3("/tmp/src", "xxx/xxx") or UploadToS3("/tmp/src", "your-cdn.s3.ap-southeast-1.amazonaws.com")
     196 + vm.Set(UploadToS3, func(call otto.FunctionCall) otto.Value {
    193 197   args := call.ArgumentList
     198 + bucket := ""
    194 199   src := args[0].String()
    195  - output := args[1].String()
    196  - execution.GetFileFromCDN(options, src, output)
     200 + if len(args) > 1 {
     201 + bucket = args[1].String()
     202 + }
     203 + 
     204 + // if bucket is empty, use the default one
     205 + if bucket == "" {
     206 + bucket = options.Cdn.Bucket
     207 + }
     208 + 
     209 + execution.UploadToS3(options, src, bucket)
    197 210   return otto.Value{}
    198 211   })
    199 212   
    200  - vm.Set(GetWSFromCDN, func(call otto.FunctionCall) otto.Value {
     213 + // DownloadFromS3("xxx", "/tmp/dest")
     214 + vm.Set(DownloadFromS3, func(call otto.FunctionCall) otto.Value {
    201 215   args := call.ArgumentList
     216 + bucket := ""
    202 217   src := args[0].String()
    203  - output := args[1].String()
    204  - execution.GetWSFromCDN(options, src, output)
     218 + dest := args[1].String()
     219 + if len(args) > 2 {
     220 + bucket = args[2].String()
     221 + }
     222 + 
     223 + // if bucket is empty, use the default one
     224 + if bucket == "" {
     225 + bucket = options.Cdn.Bucket
     226 + }
     227 + 
     228 + execution.DownloadFromS3(options, src, dest, bucket)
    205 229   return otto.Value{}
    206 230   })
    207 231   
     232 + // DownloadFile("https://xxx.com", "/tmp/dest")
    208 233   vm.Set(DownloadFile, func(call otto.FunctionCall) otto.Value {
    209 234   args := call.ArgumentList
    210 235   src := args[0].String()
    skipped 1 lines
    212 237   execution.DownloadFile(options, src, output)
    213 238   return otto.Value{}
    214 239   })
     240 + 
     241 + /* --- end CDN S3 Bucket --- */
     242 + 
    215 243   /* --- Gitlab API --- */
    216 244   
    217 245   // CreateRepo("repo-name")
    skipped 36 lines
    254 282   execution.ListProjects(0, options)
    255 283   return otto.Value{}
    256 284   })
     285 + 
     286 + /* --- end Gitlab API --- */
    257 287   
    258 288   return output
    259 289  }
    skipped 1 lines
  • ■ ■ ■ ■ ■ ■
    core/flow.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
    5  - "github.com/j3ssie/osmedeus/utils"
    6  - "github.com/thoas/go-funk"
    7 5   "path"
    8 6   "path/filepath"
    9 7   "strings"
     8 + 
     9 + "github.com/fatih/color"
     10 + "github.com/j3ssie/osmedeus/utils"
     11 + "github.com/thoas/go-funk"
    10 12   
    11 13   "github.com/j3ssie/osmedeus/libs"
    12 14  )
    skipped 105 lines
    118 120   }
    119 121   selectedModules = funk.UniqString(selectedModules)
    120 122   
    121  - utils.DebugF("Select module name %v: %v", moduleNames, selectedModules)
     123 + utils.DebugF("Select module name %v: %v", color.HiCyanString("%v", moduleNames), selectedModules)
    122 124   return selectedModules
    123 125  }
    124 126   
    skipped 97 lines
  • ■ ■ ■ ■ ■ ■
    core/parse.go
    skipped 2 lines
    3 3  import (
    4 4   "bytes"
    5 5   "fmt"
    6  - "github.com/Jeffail/gabs/v2"
    7  - "github.com/fatih/color"
    8  - "github.com/flosch/pongo2/v6"
    9  - "github.com/spf13/cast"
    10  - "golang.org/x/net/publicsuffix"
    11 6   "io/ioutil"
    12 7   "net/url"
    13 8   "os"
    skipped 2 lines
    16 11   "strings"
    17 12   "text/template"
    18 13   "time"
     14 + 
     15 + "github.com/Jeffail/gabs/v2"
     16 + "github.com/fatih/color"
     17 + "github.com/flosch/pongo2/v6"
     18 + "github.com/spf13/cast"
     19 + "golang.org/x/net/publicsuffix"
    19 20   
    20 21   "github.com/Shopify/yaml"
    21 22   "github.com/j3ssie/osmedeus/libs"
    skipped 145 lines
    167 168   ROptions["baseThreads"] = cast.ToString(options.Threads)
    168 169   
    169 170   ROptions["Version"] = libs.VERSION
    170  - ROptions["WSCDN"] = options.Cdn.WSURL
    171  - ROptions["CDN"] = options.Cdn.URL
     171 + ROptions["Bucket"] = options.Cdn.Bucket
    172 172   ROptions["Date"] = time.Now().Format("2006-01-02")
    173 173   ROptions["TS"] = utils.GetCurrentDay()
    174 174   
    skipped 3 lines
    178 178   ROptions["Plugins"] = options.Env.BinariesFolder
    179 179   ROptions["Binaries"] = options.Env.BinariesFolder
    180 180   
     181 + ROptions["Backup"] = options.Env.BackupFolder
    181 182   ROptions["Data"] = options.Env.DataFolder
    182 183   ROptions["Workflow"] = options.Env.WorkFlowsFolder
    183 184   ROptions["Scripts"] = options.Env.WorkFlowsFolder
    184 185   ROptions["Cloud"] = options.Env.CloudConfigFolder
    185 186   
    186 187   // ~/.osmedeus/clouds
    187  - //ROptions["CWorkspaces"] = options.Env.CloudDataFolder
    188 188   ROptions["Workspaces"] = options.Env.WorkspacesFolder
    189 189   if options.Scan.BaseWorkspace != "" {
    190 190   ROptions["Workspaces"] = options.Scan.BaseWorkspace
    skipped 131 lines
  • ■ ■ ■ ■ ■ ■
    core/reference.go
    skipped 73 lines
    74 74  )
    75 75   
    76 76  const (
    77  - RRSync = "RRSync"
    78  - Clone = "Clone"
    79  - FClone = "FClone"
    80  - PushResult = "PushResult"
    81  - PushFolder = "PushFolder"
    82  - PullFolder = "PullFolder"
    83  - DiffCompare = "DiffCompare"
    84  - GitDiff = "GitDiff"
    85  - LoopGitDiff = "LoopGitDiff"
    86  - GetFileFromCDN = "GetFileFromCDN"
    87  - GetWSFromCDN = "GetWSFromCDN"
    88  - DownloadFile = "DownloadFile"
     77 + RRSync = "RRSync"
     78 + Clone = "Clone"
     79 + FClone = "FClone"
     80 + PushResult = "PushResult"
     81 + PushFolder = "PushFolder"
     82 + PullFolder = "PullFolder"
     83 + DiffCompare = "DiffCompare"
     84 + GitDiff = "GitDiff"
     85 + LoopGitDiff = "LoopGitDiff"
    89 86   // for gitlab API only
    90 87   CreateRepo = "CreateRepo"
    91 88   DeleteRepo = "DeleteRepo"
    92 89   DeleteRepoByPid = "DeleteRepoByPid"
    93 90   ListProjects = "ListProjects"
     91 +)
     92 + 
     93 +const (
     94 + UploadToS3 = "UploadToS3"
     95 + DownloadFromS3 = "DownloadFromS3"
     96 + DownloadFile = "DownloadFile"
    94 97  )
    95 98   
    96 99  const (
    skipped 4 lines
  • ■ ■ ■ ■ ■ ■
    core/report.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "io/ioutil"
     6 + "os"
     7 + "path"
     8 + "path/filepath"
     9 + "strings"
     10 + 
    5 11   "github.com/Jeffail/gabs/v2"
    6 12   "github.com/fatih/color"
    7 13   "github.com/j3ssie/osmedeus/libs"
    8 14   "github.com/j3ssie/osmedeus/utils"
    9 15   "github.com/olekukonko/tablewriter"
    10 16   "github.com/spf13/cast"
    11  - "io/ioutil"
    12  - "os"
    13  - "path"
    14  - "path/filepath"
    15  - "strings"
    16 17  )
    17 18   
    18 19  func ListWorkspaces(options libs.Options) (content [][]string) {
    skipped 38 lines
    57 58   }
    58 59   
    59 60   row := []string{
    60  - path.Base(ws.Name()), status, flowName, progress, wsFolder,
     61 + path.Base(color.HiMagentaString(ws.Name())), status, flowName, progress, wsFolder,
    61 62   }
    62 63   content = append(content, row)
    63 64   }
    skipped 8 lines
    72 73   table.Render()
    73 74   
    74 75   fmt.Println(color.HiGreenString("📁 Total Workspaces: ") + color.HiMagentaString("%v", len(content)))
     76 + usage := color.HiWhiteString("💡 How to view report:") + color.HiGreenString(" osmedeus view -t %v", color.HiMagentaString("[targetName]"))
     77 + fmt.Println(usage)
     78 + 
    75 79   return content
    76 80  }
    77 81   
    skipped 4 lines
    82 86   return content
    83 87   }
    84 88   
    85  - header := []string{"Workspace Name", "Module", "Report Name", "Report Path"}
    86  - 
     89 + header := []string{"Module", "Report Name", "Report Path"}
    87 90   for _, ws := range workspaces {
    88 91   if !ws.IsDir() {
    89 92   continue
    90 93   }
     94 + // compare target name with workspace name
    91 95   if target != path.Base(ws.Name()) {
    92 96   continue
    93 97   }
    94 98   wsFolder := path.Join(utils.NormalizePath(options.Env.WorkspacesFolder), ws.Name())
    95 99   
    96 100   runtimeFile := path.Join(wsFolder, "runtime")
     101 + // only listing file that in report part
    97 102   if utils.FileExists(runtimeFile) && !options.Report.Raw {
    98 103   utils.InforF("Reading information from: %v", runtimeFile)
    99 104   runtimeContent := utils.GetFileContent(runtimeFile)
     105 + 
     106 + isImported := false
     107 + if !strings.Contains(runtimeContent, options.Env.WorkspacesFolder) {
     108 + isImported = true
     109 + }
     110 + if strings.Contains(runtimeContent, "/root/.osmedeus/workspaces") {
     111 + runtimeContent = strings.ReplaceAll(runtimeContent, "/root/.osmedeus/workspaces", options.Env.WorkspacesFolder)
     112 + }
     113 + 
     114 + row := []string{"==> Workspace Name", color.HiGreenString(ws.Name()), color.HiGreenString(wsFolder)}
     115 + content = append(content, row)
    100 116   
    101 117   if jsonParsed, ok := gabs.ParseJSON([]byte(runtimeContent)); ok == nil {
    102 118   reports := jsonParsed.S("target", "reports").Children()
    skipped 4 lines
    107 123   reportPath := cast.ToString(report.S("report_path").Data())
    108 124   
    109 125   if !utils.FileExists(reportPath) {
     126 + // /root/.osmedeus/workspaces
    110 127   continue
    111 128   }
    112 129   
    113 130   row := []string{
    114  - ws.Name(), moduleName, processReport(options, reportName), processReport(options, reportPath),
     131 + moduleName, processReport(options, reportName), processReport(options, reportPath),
    115 132   }
    116  - 
    117 133   content = append(content, row)
    118 134   }
     135 + sep := []string{"==> --------", color.HiGreenString("----------"), color.HiGreenString("-----------")}
     136 + content = append(content, sep)
     137 + 
     138 + if len(content) <= 2 && isImported {
     139 + utils.WarnF("Workspace folder not found in runtime file, you might extract it from different machine that being run on different user")
     140 + utils.WarnF("💡 If you still have problem, please view it as raw format: %s", color.HiGreenString("osmedeus view -t %s --raw", target))
     141 + }
     142 + 
    119 143   }
    120 144   continue
    121 145   }
    122 146   
    123  - header = []string{"Workspace Name", "Report Name", "Report Path"}
     147 + // --raw flag: list all avaliable file
     148 + header = []string{"Report Name", "Report Path"}
    124 149   if options.Report.Static {
    125  - header = []string{"Workspace Name", "Report Name", "Report URL"}
     150 + header = []string{"Report Name", "Report URL"}
    126 151   }
     152 + row := []string{"==> Workspace Name", color.HiGreenString(ws.Name())}
     153 + content = append(content, row)
     154 + 
    127 155   filepath.Walk(wsFolder, func(reportPath string, _ os.FileInfo, err error) error {
    128 156   reportName := path.Base(reportPath)
    129  - row := []string{
    130  - ws.Name(), processReport(options, reportName), processReport(options, reportPath),
    131  - }
     157 + row := []string{processReport(options, reportName), processReport(options, reportPath)}
    132 158   content = append(content, row)
    133 159   return nil
    134 160   })
     161 + 
     162 + sep := []string{"==> --------", color.HiGreenString("-----------")}
     163 + content = append(content, sep)
     164 + 
    135 165   }
    136 166   
    137 167   table := tablewriter.NewWriter(os.Stderr)
    138  - table.SetAutoFormatHeaders(false)
     168 + table.SetAutoFormatHeaders(true)
    139 169   table.SetHeader(header)
    140 170   table.SetBorders(tablewriter.Border{Left: true, Top: true, Right: true, Bottom: true})
    141 171   table.SetColWidth(120)
    142 172   table.AppendBulk(content)
     173 + table.SetHeaderLine(true)
    143 174   table.Render()
    144 175   
    145 176   return content
    skipped 18 lines
  • ■ ■ ■ ■ ■
    distribute/background.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "strings"
     6 + "sync"
     7 + 
    5 8   "github.com/j3ssie/osmedeus/database"
    6 9   "github.com/j3ssie/osmedeus/libs"
    7 10   "github.com/j3ssie/osmedeus/provider"
    8 11   "github.com/j3ssie/osmedeus/utils"
    9  - "strings"
     12 + "github.com/panjf2000/ants"
    10 13  )
    11 14   
    12 15  func CheckingCloudInstance(opt libs.Options) {
    skipped 8 lines
    21 24   return
    22 25   }
    23 26   
    24  - utils.InforF("Checking health of %v cloud instances", len(instances))
    25  - for _, instance := range instances {
     27 + var wg sync.WaitGroup
     28 + p, _ := ants.NewPoolWithFunc(opt.Concurrency*5, func(i interface{}) {
     29 + // really start to scan
     30 + instance := i.(database.CloudInstance)
     31 + 
    26 32   providerObj, err := provider.InitProvider(instance.Provider, instance.Token)
    27 33   if err != nil {
    28  - continue
     34 + return
    29 35   }
    30 36   
    31 37   cloud := CloudRunner{
    skipped 3 lines
    35 41   cloud.Prepare()
    36 42   cloud.PublicIP = instance.IPAddress
    37 43   cloud.InstanceID = instance.InstanceID
    38  - 
    39 44   cloud.HealthCheck()
     45 + 
     46 + wg.Done()
     47 + }, ants.WithPreAlloc(true))
     48 + defer p.Release()
     49 + 
     50 + utils.InforF("Checking health of %v cloud instances", len(instances))
     51 + for _, instance := range instances {
     52 + // providerObj, err := provider.InitProvider(instance.Provider, instance.Token)
     53 + // if err != nil {
     54 + // continue
     55 + // }
     56 + 
     57 + // cloud := CloudRunner{
     58 + // Opt: opt,
     59 + // Provider: providerObj,
     60 + // }
     61 + // cloud.Prepare()
     62 + // cloud.PublicIP = instance.IPAddress
     63 + // cloud.InstanceID = instance.InstanceID
     64 + // cloud.HealthCheck()
     65 + 
     66 + wg.Add(1)
     67 + _ = p.Invoke(instance)
    40 68   }
     69 + wg.Wait()
     70 + 
    41 71  }
    42 72   
    43 73  func (c *CloudRunner) HealthCheck() bool {
    skipped 62 lines
  • ■ ■ ■ ■ ■
    distribute/cloud.go distribute/cloud_runner.go
    1 1  package distribute
    2 2   
    3 3  import (
     4 + "fmt"
     5 + "os"
     6 + "strings"
     7 + "sync"
     8 + 
     9 + "github.com/fatih/color"
    4 10   "github.com/j3ssie/osmedeus/core"
    5 11   "github.com/j3ssie/osmedeus/database"
    6 12   "github.com/j3ssie/osmedeus/libs"
    7 13   "github.com/j3ssie/osmedeus/provider"
    8 14   "github.com/j3ssie/osmedeus/utils"
    9 15   "github.com/panjf2000/ants"
    10  - "os"
    11  - "strings"
    12  - "sync"
    13 16  )
    14 17   
    15 18  type CloudRunner struct {
    skipped 12 lines
    28 31   DestInstance string
    29 32   SshPublicKey string
    30 33   SshPrivateKey string
     34 + SSHUser string
     35 + BasePath string
    31 36   
    32 37   InstanceID string
    33 38   InstanceName string
    skipped 44 lines
    78 83   //}
    79 84   
    80 85   target = PrepareTarget(target, options)
    81  - utils.BlockF("start-scan", utils.CleanPath(target))
     86 + if !options.Cloud.OnlyCreateDroplet {
     87 + utils.BlockF("start-scan", utils.CleanPath(target))
     88 + }
    82 89   
    83 90   // really start to run scan here
    84 91   err := selectedCloud.Scan(target)
    skipped 3 lines
    88 95   continue
    89 96   }
    90 97   
    91  - utils.BlockF("done-scan", utils.CleanPath(target))
    92  - utils.InforF("--------------------------------")
     98 + if !options.Cloud.OnlyCreateDroplet {
     99 + utils.BlockF("done-scan", utils.CleanPath(target))
     100 + utils.InforF("--------------------------------")
     101 + }
    93 102   isDone = true
    94 103   }
    95 104   break
    skipped 21 lines
    117 126   
    118 127   // parse config from cloud/config.yaml file
    119 128   providerConfigs, err := provider.ParseProvider(options.CloudConfigFile)
    120  - utils.DebugF("Parsing cloud config from: %s", options.CloudConfigFile)
     129 + utils.DebugF("Parsing cloud config from: %s", color.HiCyanString(options.CloudConfigFile))
    121 130   if err != nil {
    122 131   return cloudInfos
    123 132   }
    skipped 23 lines
    147 156   cloudInfos = append(cloudInfos, cloudInfo)
    148 157   }
    149 158   
    150  - utils.InforF("Number of cloud provider prepared in queue: %v", len(cloudInfos))
     159 + utils.InforF("Number of cloud providers ready in queue: %v", color.HiMagentaString("%v", len(cloudInfos)))
    151 160   return cloudInfos
    152 161  }
    153 162   
    skipped 9 lines
    163 172   }
    164 173   cloudRunner.Provider = providerCloud
    165 174   
     175 + // custom user for aws
     176 + if cloudRunner.Provider.ProviderName == "aws" {
     177 + cloudRunner.SSHUser = "admin"
     178 + }
     179 + if cloudRunner.SSHUser != "root" {
     180 + cloudRunner.BasePath = fmt.Sprintf("/home/%s", cloudRunner.SSHUser)
     181 + }
     182 + 
    166 183   if opt.Cloud.IgnoreSetup {
    167 184   return cloudRunner
    168 185   }
    skipped 14 lines
    183 200  func (c *CloudRunner) Prepare() {
    184 201   c.SshPrivateKey = c.Opt.Cloud.SecretKey
    185 202   c.SshPublicKey = c.Opt.Cloud.PublicKey
     203 + c.SSHUser = "root"
     204 + c.BasePath = "/root"
    186 205   
    187 206   // make sure the permission of private key is right
    188 207   os.Chmod(utils.NormalizePath(c.SshPrivateKey), 0600)
    skipped 5 lines
  • ■ ■ ■ ■ ■ ■
    distribute/create.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
    5  - "github.com/j3ssie/osmedeus/core"
    6  - "github.com/j3ssie/osmedeus/utils"
    7 5   "path"
    8 6   "strings"
     7 + 
     8 + "github.com/fatih/color"
     9 + "github.com/j3ssie/osmedeus/core"
     10 + "github.com/j3ssie/osmedeus/utils"
    9 11  )
    10 12   
    11 13  func (c *CloudRunner) CreateInstance(target string) error {
    skipped 56 lines
    68 70   }
    69 71   
    70 72   /* Really start to run command to create instance here */
    71  - err := c.Provider.CreateInstanceF(c.InstanceName)
     73 + err := c.Provider.CreateInstance(c.InstanceName)
    72 74   
    73 75   // @TODO: naming in linode might need another check for length
    74 76   if err != nil {
    skipped 19 lines
    94 96   c.PublicIP = c.Provider.CreatedInstance.IPAddress
    95 97   
    96 98   c.InstanceID = c.Provider.CreatedInstance.InstanceID
    97  - c.DestInstance = fmt.Sprintf("root@%s", c.PublicIP)
    98  - utils.InforF("Creating instance: %s -- %v", c.InstanceName, c.PublicIP)
     99 + c.DestInstance = fmt.Sprintf("%s@%s", c.SSHUser, c.PublicIP)
     100 + utils.InforF("Instance created: %s -- %s -- %v", color.HiCyanString(c.InstanceName), color.HiCyanString(c.InstanceID), color.HiCyanString(c.PublicIP))
    99 101   c.Target["CIP"] = c.PublicIP
    100 102   c.Target["RemoteIP"] = c.PublicIP
    101 103   
    skipped 4 lines
  • ■ ■ ■ ■ ■
    distribute/mics.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
    5  - "github.com/j3ssie/osmedeus/libs"
    6  - "github.com/j3ssie/osmedeus/utils"
    7 5   "path"
    8 6   "strings"
     7 + 
     8 + "github.com/j3ssie/osmedeus/libs"
     9 + "github.com/j3ssie/osmedeus/utils"
     10 + "github.com/spf13/cast"
    9 11  )
    10 12   
    11 13  // CommandBuilder build core command from API
    skipped 6 lines
    18 20   
    19 21   if options.Update.EnableUpdate {
    20 22   binary += " --update"
     23 + }
     24 + 
     25 + if options.Threads > 0 {
     26 + binary += " --threads-hold " + cast.ToString(options.Threads)
    21 27   }
    22 28   
    23 29   if options.ScanID != "" {
    skipped 87 lines
  • ■ ■ ■ ■ ■ ■
    distribute/scan.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "path"
     6 + "strings"
     7 + "time"
     8 + 
    5 9   "github.com/fatih/color"
    6 10   "github.com/j3ssie/osmedeus/core"
    7 11   "github.com/j3ssie/osmedeus/libs"
    8 12   "github.com/j3ssie/osmedeus/provider"
    9 13   "github.com/j3ssie/osmedeus/utils"
    10  - "path"
    11  - "strings"
    12  - "time"
    13 14  )
    14 15   
    15 16  func (c *CloudRunner) PrepareInput() {
    skipped 39 lines
    55 56   return fmt.Errorf("error to start the scan")
    56 57   }
    57 58   
    58  - utils.InforF("Create UI report for %s: %s", c.DestInstance, color.HiCyanString(c.Opt.Cloud.RawCommand))
    59  - //database.ScanDone(c.Opt, c.Target["Workspace"])
     59 + utils.DebugF("Create UI report for %s: %s", c.DestInstance, color.HiCyanString(c.Opt.Cloud.RawCommand))
    60 60   c.Runner.DBDoneScan()
    61 61   c.CreateUIReport()
    62 62   return nil
    skipped 30 lines
    93 93   utils.ErrorF(out)
    94 94   return fmt.Errorf("error running command on %v", c.DestInstance)
    95 95   }
    96  - utils.InforF("Start to run %v -- %v", c.DestInstance, c.Opt.Cloud.RawCommand)
     96 + utils.InforF("Start to run the scan %v with command %v", color.HiYellowString(c.DestInstance), color.HiCyanString(c.Opt.Cloud.RawCommand))
    97 97   
    98 98   // wait a bit for process really start
    99  - time.Sleep(60)
     99 + time.Sleep(60 * time.Second)
    100 100   if !c.IsRunning() {
    101 101   // @TODO: update DB cloud table for panic detected
    102 102   c.DBErrorCloudScan()
    skipped 7 lines
    110 110   if c.Opt.Cloud.NoDelete {
    111 111   return nil
    112 112   }
    113  - utils.InforF("Checking scan process at: %s", c.PublicIP)
    114  - dest := fmt.Sprintf("/root/.%s/workspaces/%s/done", libs.BINARY, c.Target["Workspace"])
     113 + utils.InforF("Checking scan process at: %s", color.HiBlueString(c.PublicIP))
     114 + dest := fmt.Sprintf("%s/.%s/workspaces/%s/done", c.BasePath, libs.BINARY, c.Target["Workspace"])
    115 115   cmd := fmt.Sprintf("file %s", dest)
    116 116   out, _ := c.SSHExec(cmd)
    117 117   
    skipped 7 lines
    125 125   time.Sleep(time.Duration(waitTime) * time.Second)
    126 126   out, _ = c.SSHExec(cmd)
    127 127   if strings.Contains(out, "ASCII text") || strings.Contains(out, "JSON data") {
    128  - utils.InforF("The scan is done at: %s", c.PublicIP)
     128 + utils.InforF("The scan is done at: %s", color.HiBlueString(c.PublicIP))
    129 129   return nil
    130 130   }
    131 131   
    skipped 20 lines
    152 152   
    153 153  func (c *CloudRunner) SyncResult() error {
    154 154   target := c.Opt.Cloud.Input
    155  - utils.InforF("Sync back of %v from %v", target, c.DestInstance)
     155 + utils.InforF("Sync back the data of taget %v from %v", color.HiCyanString(target), color.HiYellowString(c.DestInstance))
    156 156   // on vps machine
    157 157   src := c.Opt.Cloud.LocalSyncFolder
    158 158   
    skipped 33 lines
    192 192   
    193 193  func (c *CloudRunner) CopyWorkflow() error {
    194 194   utils.DebugF("Sync workflow of %s to %s", c.Opt.Env.WorkFlowsFolder, c.DestInstance)
    195  - destWorkflow := "/root/osmedeus-base/workflow/"
     195 + destWorkflow := fmt.Sprintf("%v/osmedeus-base/workflow/", c.BasePath)
    196 196   if c.Opt.Cloud.RemoteWorkflowFolder != "" {
    197 197   destWorkflow = c.Opt.Cloud.RemoteWorkflowFolder
    198 198   }
    skipped 61 lines
  • ■ ■ ■ ■ ■ ■
    distribute/ssh.go
    skipped 10 lines
    11 11   "strings"
    12 12   "time"
    13 13   
     14 + "github.com/fatih/color"
    14 15   "github.com/j3ssie/osmedeus/utils"
    15 16   
    16 17   "golang.org/x/crypto/ssh"
    skipped 6 lines
    23 24   return "", err
    24 25   }
    25 26   
    26  - utils.DebugF("Running command on %s: %s", c.PublicIP, command)
     27 + utils.DebugF("Running command on %s: %s", color.HiBlueString(c.PublicIP), color.HiGreenString(command))
    27 28   out, err := client.Cmd(command).Output()
    28 29   if err != nil {
    29 30   utils.ErrorF("err run command: %v", err)
    skipped 4 lines
    34 35   
    35 36  func (c *CloudRunner) InitSSHClient() (*Client, error) {
    36 37   host := fmt.Sprintf("%s:%s", c.PublicIP, "22")
    37  - utils.DebugF("Connecting to %v with key %v", host, c.SshPrivateKey)
    38  - client, err := DialWithKeyString(host, "root", c.Opt.Cloud.SecretKeyContent)
     38 + dest := color.HiCyanString("%s@%s", c.SSHUser, host)
     39 + utils.DebugF("Connecting to %v with key %v", dest, c.SshPrivateKey)
     40 + client, err := DialWithKeyString(host, c.SSHUser, c.Opt.Cloud.SecretKeyContent)
    39 41   if err != nil {
    40 42   utils.ErrorF("err connect to %v -- %v", host, err)
    41 43   for i := 0; i < c.Opt.Cloud.Retry; i++ {
    42  - client, err = DialWithKeyString(host, "root", c.Opt.Cloud.SecretKeyContent)
    43  - //client, err = DialWithKey(host, "root", c.SshPrivateKey)
     44 + client, err = DialWithKeyString(host, c.SSHUser, c.Opt.Cloud.SecretKeyContent)
    44 45   if err != nil {
    45 46   time.Sleep(time.Duration(30*(i+1)) * time.Second)
    46 47   continue
    skipped 383 lines
  • ■ ■ ■ ■ ■
    distribute/wizard.go
    skipped 2 lines
    3 3  import (
    4 4   "bufio"
    5 5   "fmt"
     6 + "os"
     7 + "strings"
     8 + "syscall"
     9 + 
    6 10   "github.com/Shopify/yaml"
    7 11   "github.com/fatih/color"
    8 12   "github.com/j3ssie/osmedeus/libs"
    skipped 1 lines
    10 14   "github.com/j3ssie/osmedeus/utils"
    11 15   "github.com/olekukonko/tablewriter"
    12 16   "golang.org/x/term"
    13  - "os"
    14  - "strings"
    15  - "syscall"
    16 17  )
    17 18   
    18 19  func InitCloudSetup(opt libs.Options) {
    19  - var supportedProvider = []string{"digitalocean", "linode"}
     20 + var supportedProvider = []string{"aws", "digitalocean", "linode"}
    20 21   fmt.Println("🔮 Start cloud setup wizard 🔮")
    21 22   fmt.Println("Currently only these providers are supported: ", color.HiYellowString("%v", supportedProvider))
    22 23   
    skipped 108 lines
    131 132   Limit: 0,
    132 133   }
    133 134   fmt.Printf("==> provider selected: %s\n", color.HiBlueString("linode"))
     135 + case "aw", "asw", "aws":
     136 + configProvider = provider.ConfigProvider{
     137 + AccessKeyId: "",
     138 + SecretKey: "",
     139 + Provider: "aws",
     140 + DefaultImage: "ami-0ee39036464b9a87e",
     141 + Size: "t2.medium",
     142 + Region: "ap-southeast-1",
     143 + Limit: 0,
     144 + }
     145 + fmt.Printf("==> provider selected: %s\n", color.HiBlueString("aws"))
    134 146   
    135 147   default:
    136 148   configProvider.Provider = "digitalocean"
    137 149   fmt.Printf("==> provider selected: %s\n", color.HiBlueString("digitalocean"))
     150 + }
    138 151   
     152 + if configProvider.Provider == "aws" {
     153 + configProvider.AccessKeyId = credentials("AWS AccessKeyId")
     154 + fmt.Println()
     155 + configProvider.SecretKey = credentials("AWS SecretKey")
     156 + fmt.Println()
     157 + } else {
     158 + configProvider.Token = credentials("API Token")
    139 159   }
    140 160   
    141  - configProvider.Token = credentials()
    142  - configProvider.Name = fmt.Sprintf("digitalocean-%s", utils.RandomString(6))
     161 + configProvider.Name = fmt.Sprintf("%s-%s", configProvider.Provider, utils.RandomString(6))
     162 + 
     163 + if configProvider.Provider == "aws" {
     164 + fmt.Printf("💡 Choose your image carefully because it related to region.\n")
     165 + fmt.Printf("💡 Refer for this link for more information: " + color.HiCyanString("https://wiki.debian.org/Cloud/AmazonEC2Image/Buster"))
     166 + }
    143 167   configProvider.DefaultImage = StringPrompt("\n🌀 Choose "+color.HiGreenString("base image")+" for building Osmedeus Image?", configProvider.DefaultImage)
    144 168   configProvider.Size = StringPrompt("🌀 Choose "+color.HiGreenString("instance type")+" for running the scan?", configProvider.Size)
    145 169   configProvider.Region = StringPrompt("🌀 Choose "+color.HiGreenString("instance region")+" for running the scan?", configProvider.Region)
    skipped 1 lines
    147 171   return configProvider
    148 172  }
    149 173   
    150  -func credentials() string {
    151  - fmt.Printf(" Enter your %s? ", color.HiGreenString("API token"))
     174 +func credentials(name string) string {
     175 + fmt.Printf(" Enter your %s? ", color.HiGreenString(name))
    152 176   var token string
    153 177   for {
    154 178   byteToken, err := term.ReadPassword(int(syscall.Stdin))
    skipped 2 lines
    157 181   break
    158 182   }
    159 183   utils.WarnF("Looks like your token is invalid. Please try again: %v", token)
    160  - 
    161 184   }
    162 185   
    163 186   redactedToken := token[:5] + "***" + token[len(token)-5:]
    164  - fmt.Printf("Your token has been saved: %v", color.HiBlueString(redactedToken))
     187 + fmt.Printf("Your data has been saved: %v", color.HiBlueString(redactedToken))
    165 188   return token
    166 189  }
    167 190   
    skipped 47 lines
  • ■ ■ ■ ■ ■ ■
    execution/cdn.go
    1  -package execution
    2  - 
    3  -import (
    4  - "fmt"
    5  - "net/url"
    6  - "os"
    7  - "path"
    8  - 
    9  - "github.com/j3ssie/osmedeus/libs"
    10  - "github.com/j3ssie/osmedeus/utils"
    11  - jsoniter "github.com/json-iterator/go"
    12  -)
    13  - 
    14  -type CdnSummary struct {
    15  - Targets []Cdn `json:"targets"`
    16  - UpdateDate string `json:"update_date"`
    17  - Total int `json:"total"`
    18  -}
    19  - 
    20  -type Cdn struct {
    21  - TargetName string `json:"target_name"`
    22  - DownloadURL string `json:"download_url"`
    23  - Type string `json:"type"`
    24  -}
    25  - 
    26  -// GetTargetFromCDN search for target from CDN Index
    27  -func GetTargetFromCDN(options libs.Options, targetWS string) string {
    28  - utils.DebugF("Finding targets from CDN: %s", options.Cdn.Index)
    29  - resp, err := SendGET("", options.Cdn.Index)
    30  - if err != nil {
    31  - return ""
    32  - }
    33  - 
    34  - var cdnSummary CdnSummary
    35  - err = jsoniter.UnmarshalFromString(resp.Body, &cdnSummary)
    36  - if err != nil {
    37  - utils.WarnF("error parsing body")
    38  - return ""
    39  - }
    40  - 
    41  - if len(cdnSummary.Targets) == 0 {
    42  - utils.WarnF("index file empty")
    43  - return ""
    44  - }
    45  - 
    46  - for _, target := range cdnSummary.Targets {
    47  - if targetWS == target.TargetName {
    48  - return target.DownloadURL
    49  - }
    50  - // in case we have typo
    51  - if targetWS == fmt.Sprintf("%s.zip", target.TargetName) {
    52  - return target.DownloadURL
    53  - }
    54  - }
    55  - utils.WarnF("no target match")
    56  - return ""
    57  -}
    58  - 
    59  -// GetFileFromCDN get file from CDN URL
    60  -func GetFileFromCDN(options libs.Options, filename string, dest string) {
    61  - if options.NoCdn {
    62  - return
    63  - }
    64  - 
    65  - u, err := url.Parse(options.Cdn.URL)
    66  - if err != nil {
    67  - return
    68  - }
    69  - u.Path = path.Join(u.Path, filename)
    70  - downloadURL := u.String()
    71  - utils.DebugF("Downloading: %s", downloadURL)
    72  - 
    73  - if !utils.FolderExists(path.Dir(dest)) {
    74  - utils.MakeDir(path.Dir(dest))
    75  - }
    76  - 
    77  - cmd := fmt.Sprintf("wget -qO %s %s", dest, downloadURL)
    78  - Execution(cmd, options)
    79  - if utils.FileLength(dest) <= 0 {
    80  - os.RemoveAll(dest)
    81  - return
    82  - }
    83  -}
    84  - 
    85  -// GetWSFromCDN get workspace zip from CDN URL
    86  -func GetWSFromCDN(options libs.Options, target string, dest string) {
    87  - if options.NoCdn {
    88  - return
    89  - }
    90  - 
    91  - downloadURL := GetTargetFromCDN(options, target)
    92  - if downloadURL == "" {
    93  - utils.WarnF("Target not found from cdn: %v", target)
    94  - return
    95  - }
    96  - 
    97  - utils.DebugF("Downloading: %s", downloadURL)
    98  - 
    99  - if !utils.FolderExists(path.Dir(dest)) {
    100  - utils.MakeDir(path.Dir(dest))
    101  - }
    102  - 
    103  - cmd := fmt.Sprintf("wget -qO %s %s", dest, downloadURL)
    104  - Execution(cmd, options)
    105  - if utils.FileLength(dest) <= 0 {
    106  - os.RemoveAll(dest)
    107  - return
    108  - }
    109  -}
    110  - 
    111  -// DownloadFile get file from CDN URL
    112  -func DownloadFile(options libs.Options, downloadURL string, dest string) {
    113  - utils.DebugF("Downloading: %s", downloadURL)
    114  - if !utils.FolderExists(path.Dir(dest)) {
    115  - utils.MakeDir(path.Dir(dest))
    116  - }
    117  - 
    118  - cmd := fmt.Sprintf("wget -qO %s %s", dest, downloadURL)
    119  - Execution(cmd, options)
    120  - 
    121  - if utils.FileLength(dest) <= 0 {
    122  - os.RemoveAll(dest)
    123  - return
    124  - }
    125  - 
    126  -}
    127  - 
  • ■ ■ ■ ■ ■ ■
    execution/s3_cdn.go
     1 +package execution
     2 + 
     3 +import (
     4 + "fmt"
     5 + "io"
     6 + "os"
     7 + "path"
     8 + 
     9 + "github.com/aws/aws-sdk-go/aws"
     10 + "github.com/aws/aws-sdk-go/aws/credentials"
     11 + "github.com/aws/aws-sdk-go/aws/session"
     12 + "github.com/aws/aws-sdk-go/service/s3"
     13 + "github.com/fatih/color"
     14 + "github.com/j3ssie/osmedeus/libs"
     15 + "github.com/j3ssie/osmedeus/utils"
     16 +)
     17 + 
     18 +// UploadToS3 upload local file to s3 bucket
     19 +func UploadToS3(options libs.Options, source string, bucket string) {
     20 + if options.Cdn.AccessKeyId == "CDN_AWS_ACCESS_KEY" {
     21 + return
     22 + }
     23 + utils.InforF("Uploading %s to %s", color.HiCyanString(source), color.HiCyanString(bucket))
     24 + // Set up a new session and get a reference to the S3 service.
     25 + sess, err := session.NewSession(&aws.Config{
     26 + Credentials: credentials.NewStaticCredentials(options.Cdn.AccessKeyId, options.Cdn.SecretKey, ""),
     27 + Region: aws.String(options.Cdn.Region)},
     28 + )
     29 + if err != nil {
     30 + utils.ErrorF("error creating session: %s", err)
     31 + return
     32 + }
     33 + svc := s3.New(sess)
     34 + 
     35 + if !utils.FileExists(source) {
     36 + utils.ErrorF("File not found: %s", source)
     37 + return
     38 + }
     39 + 
     40 + // Open the file that you want to upload.
     41 + file, err := os.Open(source)
     42 + if err != nil {
     43 + utils.ErrorF("error opening file: %s", err)
     44 + return
     45 + }
     46 + defer file.Close()
     47 + 
     48 + // Set up the parameters for the upload.
     49 + params := &s3.PutObjectInput{
     50 + Bucket: aws.String(bucket),
     51 + Key: aws.String(source),
     52 + Body: file,
     53 + }
     54 + 
     55 + // Upload the file to S3.
     56 + _, err = svc.PutObject(params)
     57 + if err != nil {
     58 + utils.ErrorF("error uploading file: %s", err)
     59 + return
     60 + }
     61 +}
     62 + 
     63 +// DownloadFromS3 upload local file to s3 bucket
     64 +func DownloadFromS3(options libs.Options, source string, dest string, bucket string) {
     65 + if options.Cdn.AccessKeyId == "CDN_AWS_ACCESS_KEY" {
     66 + return
     67 + }
     68 + utils.InforF("Downloading %s from %s bucket to %s", color.HiCyanString(source), color.HiCyanString(bucket), color.HiBlueString(dest))
     69 + // Set up a new session and get a reference to the S3 service.
     70 + sess, err := session.NewSession(&aws.Config{
     71 + Credentials: credentials.NewStaticCredentials(options.Cdn.AccessKeyId, options.Cdn.SecretKey, ""),
     72 + Region: aws.String(options.Cdn.Region)},
     73 + )
     74 + if err != nil {
     75 + utils.ErrorF("error creating session: %s", err)
     76 + return
     77 + }
     78 + svc := s3.New(sess)
     79 + 
     80 + // Set up the parameters for the download.
     81 + params := &s3.GetObjectInput{
     82 + Bucket: aws.String(bucket),
     83 + Key: aws.String(source),
     84 + }
     85 + 
     86 + // Download the file from S3.
     87 + result, err := svc.GetObject(params)
     88 + if err != nil {
     89 + utils.ErrorF("error downloading file: %s", err)
     90 + return
     91 + }
     92 + defer result.Body.Close()
     93 + 
     94 + // Create a local file to store the downloaded data.
     95 + outFile, err := os.Create(dest)
     96 + if err != nil {
     97 + utils.ErrorF("error creating local file: %s", err)
     98 + return
     99 + }
     100 + defer outFile.Close()
     101 + 
     102 + // Copy the data from the S3 object to the local file.
     103 + _, err = io.Copy(outFile, result.Body)
     104 + if err != nil {
     105 + utils.ErrorF("error copying file data: %s", err)
     106 + return
     107 + }
     108 +}
     109 + 
     110 +// DownloadFile get file from CDN URL
     111 +func DownloadFile(options libs.Options, downloadURL string, dest string) {
     112 + utils.DebugF("Downloading: %s", downloadURL)
     113 + if !utils.FolderExists(path.Dir(dest)) {
     114 + utils.MakeDir(path.Dir(dest))
     115 + }
     116 + 
     117 + cmd := fmt.Sprintf("wget -qO %s %s", dest, downloadURL)
     118 + Execution(cmd, options)
     119 + 
     120 + if utils.FileLength(dest) <= 0 {
     121 + os.RemoveAll(dest)
     122 + return
     123 + }
     124 + 
     125 +}
     126 + 
  • ■ ■ ■ ■ ■ ■
    execution/scripts.go
    skipped 4 lines
    5 5   "bufio"
    6 6   "compress/gzip"
    7 7   "fmt"
    8  - "github.com/j3ssie/osmedeus/libs"
    9 8   "io"
    10 9   "io/ioutil"
    11 10   "os"
    skipped 3 lines
    15 14   "sort"
    16 15   "strings"
    17 16   "time"
     17 + 
     18 + "github.com/j3ssie/osmedeus/libs"
    18 19   
    19 20   "github.com/j3ssie/osmedeus/utils"
    20 21  )
    skipped 141 lines
    162 163   utils.DebugF("Folder is empty or not found: %s", src)
    163 164   return
    164 165   }
    165  - cmd := fmt.Sprintf("tar --use-compress-program='gzip -9' -cf %s %s", dest, strings.TrimRight(src, "/"))
     166 + cmd := fmt.Sprintf("tar --use-compress-program='gzip -9' -C %s -cf %s .", strings.TrimRight(src, "/"), dest)
    166 167   utils.RunCmdWithOutput(cmd)
    167 168  }
    168 169   
    skipped 3 lines
    172 173   utils.DebugF("File not found: %s", src)
    173 174   return
    174 175   }
    175  - 
     176 + utils.MakeDir(dest)
    176 177   cmd := fmt.Sprintf("tar -xf %s -C %s", src, dest)
    177 178   utils.RunCmdWithOutput(cmd)
    178 179  }
    skipped 48 lines
  • ■ ■ ■ ■ ■ ■
    go.mod
    skipped 5 lines
    6 6   github.com/Jeffail/gabs/v2 v2.6.1
    7 7   github.com/Shopify/yaml v2.1.0+incompatible
    8 8   github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
     9 + github.com/aws/aws-sdk-go v1.44.162
    9 10   github.com/cenkalti/backoff/v4 v4.2.0
    10 11   github.com/davecgh/go-spew v1.1.1
    11 12   github.com/dgrijalva/jwt-go v3.2.0+incompatible
    12  - github.com/digitalocean/godo v1.90.0
     13 + github.com/digitalocean/godo v1.93.0
    13 14   github.com/fatih/color v1.13.0
    14 15   github.com/flosch/pongo2/v6 v6.0.0
    15 16   github.com/fsnotify/fsnotify v1.6.0
    16 17   github.com/go-playground/validator/v10 v10.11.1
    17 18   github.com/go-resty/resty/v2 v2.7.0
    18 19   github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible
    19  - github.com/gofiber/fiber/v2 v2.40.0
     20 + github.com/gofiber/fiber/v2 v2.40.1
    20 21   github.com/gofiber/jwt/v2 v2.2.7
    21 22   github.com/hashicorp/go-version v1.6.0
    22 23   github.com/jasonlvhit/gocron v0.0.1
    skipped 6 lines
    29 30   github.com/olekukonko/tablewriter v0.0.5
    30 31   github.com/panjf2000/ants v1.3.0
    31 32   github.com/parnurzeal/gorequest v0.2.16
    32  - github.com/robertkrimen/otto v0.0.0-20221025135307-511d75fba9f8
     33 + github.com/robertkrimen/otto v0.2.1
    33 34   github.com/shirou/gopsutil v3.21.11+incompatible
    34 35   github.com/sirupsen/logrus v1.9.0
    35  - github.com/slack-go/slack v0.11.4
     36 + github.com/slack-go/slack v0.12.0
    36 37   github.com/spf13/cast v1.5.0
    37 38   github.com/spf13/cobra v1.6.1
    38 39   github.com/spf13/viper v1.14.0
    39  - github.com/swaggo/swag v1.8.7
     40 + github.com/swaggo/swag v1.8.9
    40 41   github.com/thoas/go-funk v0.9.2
    41 42   github.com/x-cray/logrus-prefixed-formatter v0.5.2
    42  - github.com/xanzy/go-gitlab v0.75.0
    43  - golang.org/x/crypto v0.3.0
    44  - golang.org/x/net v0.2.0
    45  - golang.org/x/oauth2 v0.2.0
    46  - golang.org/x/term v0.2.0
    47  - golang.org/x/text v0.4.0
    48  - gorm.io/datatypes v1.0.7
     43 + github.com/xanzy/go-gitlab v0.77.0
     44 + golang.org/x/crypto v0.4.0
     45 + golang.org/x/net v0.4.0
     46 + golang.org/x/oauth2 v0.3.0
     47 + golang.org/x/term v0.3.0
     48 + golang.org/x/text v0.5.0
     49 + gorm.io/datatypes v1.1.0
    49 50   gorm.io/driver/mysql v1.4.4
    50 51   gorm.io/driver/sqlite v1.4.3
    51  - gorm.io/gorm v1.24.1
     52 + gorm.io/gorm v1.24.2
    52 53  )
    53 54   
    54 55  require (
    skipped 9 lines
    64 65   github.com/go-openapi/swag v0.19.15 // indirect
    65 66   github.com/go-playground/locales v0.14.0 // indirect
    66 67   github.com/go-playground/universal-translator v0.18.0 // indirect
    67  - github.com/go-sql-driver/mysql v1.6.0 // indirect
     68 + github.com/go-sql-driver/mysql v1.7.0 // indirect
    68 69   github.com/golang-jwt/jwt/v4 v4.0.0 // indirect
    69 70   github.com/golang/protobuf v1.5.2 // indirect
    70 71   github.com/google/go-querystring v1.1.0 // indirect
    skipped 4 lines
    75 76   github.com/inconshreveable/mousetrap v1.0.1 // indirect
    76 77   github.com/jinzhu/inflection v1.0.0 // indirect
    77 78   github.com/jinzhu/now v1.1.5 // indirect
     79 + github.com/jmespath/go-jmespath v0.4.0 // indirect
    78 80   github.com/josharian/intern v1.0.0 // indirect
    79 81   github.com/klauspost/compress v1.15.9 // indirect
    80 82   github.com/leodido/go-urn v1.2.1 // indirect
    skipped 23 lines
    104 106   github.com/valyala/fasthttp v1.41.0 // indirect
    105 107   github.com/valyala/tcplisten v1.0.0 // indirect
    106 108   github.com/yusufpapurcu/wmi v1.2.2 // indirect
    107  - golang.org/x/sys v0.2.0 // indirect
     109 + golang.org/x/sys v0.3.0 // indirect
    108 110   golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect
    109 111   golang.org/x/tools v0.1.12 // indirect
    110 112   google.golang.org/appengine v1.6.7 // indirect
    skipped 8 lines
  • ■ ■ ■ ■ ■
    go.sum
    skipped 35 lines
    36 36  cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
    37 37  cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
    38 38  dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
    39  -github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
    40  -github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
    41  -github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
    42 39  github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
    43 40  github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
    44 41  github.com/Jeffail/gabs/v2 v2.6.1 h1:wwbE6nTQTwIMsMxzi6XFQQYRZ6wDc1mSdxoAN+9U4Gk=
    45 42  github.com/Jeffail/gabs/v2 v2.6.1/go.mod h1:xCn81vdHKxFUuWWAaD5jCTQDNPBMh5pPs9IJ+NcziBI=
    46 43  github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
    47 44  github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
    48  -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
    49 45  github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
    50 46  github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
    51 47  github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
    skipped 5 lines
    57 53  github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
    58 54  github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
    59 55  github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
     56 +github.com/aws/aws-sdk-go v1.44.162 h1:hKAd+X+/BLxVMzH+4zKxbQcQQGrk2UhFX0OTu1Mhon8=
     57 +github.com/aws/aws-sdk-go v1.44.162/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
    60 58  github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
    61 59  github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
    62 60  github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
    63 61  github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
    64  -github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
    65 62  github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
    66 63  github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
    67 64  github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
    68 65  github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
    69 66  github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
    70 67  github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
    71  -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
    72  -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
    73  -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
    74 68  github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
    75  -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
    76 69  github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
    77 70  github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
    78 71  github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
    79 72  github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
    80  -github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA=
    81  -github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU=
    82 73  github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
    83 74  github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
    84  -github.com/digitalocean/godo v1.90.0 h1:mnluEWL5eXFNYnLzHFuwsPuXZsWmzGoMNYSLZi9QPgc=
    85  -github.com/digitalocean/godo v1.90.0/go.mod h1:NRpFznZFvhHjBoqZAaOD3khVzsJ3EibzKqFL4R60dmA=
    86  -github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
     75 +github.com/digitalocean/godo v1.93.0 h1:N0K9z2yssZVP7nBHQ32P1Wemd5yeiJdH4ROg+7ySRxY=
     76 +github.com/digitalocean/godo v1.93.0/go.mod h1:NRpFznZFvhHjBoqZAaOD3khVzsJ3EibzKqFL4R60dmA=
    87 77  github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0=
    88 78  github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
    89 79  github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8=
    skipped 14 lines
    104 94  github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
    105 95  github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
    106 96  github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
    107  -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
    108  -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
    109 97  github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
    110 98  github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
    111 99  github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
    skipped 17 lines
    129 117  github.com/go-redis/redis v6.15.5+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
    130 118  github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
    131 119  github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
    132  -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
    133 120  github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
    134  -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
     121 +github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
     122 +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
    135 123  github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU=
    136 124  github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
    137 125  github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
    138 126  github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
    139 127  github.com/gofiber/fiber/v2 v2.17.0/go.mod h1:iftruuHGkRYGEXVISmdD7HTYWyfS2Bh+Dkfq4n/1Owg=
    140  -github.com/gofiber/fiber/v2 v2.40.0 h1:fdU7w5hT6PLL7jiWIhtQ+S/k5WEFYoUZidptlPu8GBo=
    141  -github.com/gofiber/fiber/v2 v2.40.0/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk=
     128 +github.com/gofiber/fiber/v2 v2.40.1 h1:pc7n9VVpGIqNsvg9IPLQhyFEMJL8gCs1kneH5D1pIl4=
     129 +github.com/gofiber/fiber/v2 v2.40.1/go.mod h1:Gko04sLksnHbzLSRBFWPFdzM9Ws9pRxvvIaohJK1dsk=
    142 130  github.com/gofiber/jwt/v2 v2.2.7 h1:MgXZV+ak+FiRVepD3btHBxWcyxlFzTDGXJv78dU1sIE=
    143 131  github.com/gofiber/jwt/v2 v2.2.7/go.mod h1:yaOHLccYXJidk1HX/EiIdIL+Z1xmY2wnIv6hgViw384=
    144  -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
    145 132  github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o=
    146 133  github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
    147  -github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
    148 134  github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
    149  -github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
    150  -github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4=
    151  -github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8=
     135 +github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
    152 136  github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
    153 137  github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
    154 138  github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
    skipped 81 lines
    236 220  github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
    237 221  github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
    238 222  github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
    239  -github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
    240  -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
    241  -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
    242 223  github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
    243  -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
    244  -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
    245  -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
    246  -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
    247  -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
    248  -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
    249  -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
    250  -github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ=
    251  -github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
     224 +github.com/jackc/pgconn v1.13.0 h1:3L1XMNV2Zvca/8BYhzcRFS70Lr0WlDg16Di6SFGAbys=
    252 225  github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
    253  -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
    254  -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
    255  -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c=
    256  -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak=
    257 226  github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
    258  -github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
    259  -github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
    260  -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
    261  -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
    262  -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
    263  -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
    264  -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
    265  -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
    266  -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
    267  -github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns=
    268  -github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
     227 +github.com/jackc/pgproto3/v2 v2.3.1 h1:nwj7qwf0S+Q7ISFfBndqeLwSwxs+4DPsbRFjECT1Y4Y=
    269 228  github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
    270  -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
    271  -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
    272  -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
    273  -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
    274  -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
    275  -github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38=
    276  -github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
    277  -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
    278  -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
    279  -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
    280  -github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
    281  -github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w=
    282  -github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw=
    283  -github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
    284  -github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
    285  -github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
    286  -github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
     229 +github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
     230 +github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
    287 231  github.com/jasonlvhit/gocron v0.0.1 h1:qTt5qF3b3srDjeOIR4Le1LfeyvoYzJlYpqvG7tJX5YU=
    288 232  github.com/jasonlvhit/gocron v0.0.1/go.mod h1:k9a3TV8VcU73XZxfVHCHWMWF9SOqgoku0/QlY2yvlA4=
    289 233  github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
    skipped 1 lines
    291 235  github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
    292 236  github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
    293 237  github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
     238 +github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
     239 +github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
     240 +github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
     241 +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
    294 242  github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
    295 243  github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
    296 244  github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
    skipped 6 lines
    303 251  github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
    304 252  github.com/klauspost/compress v1.15.9 h1:wKRjX6JRtDdrE9qwa4b/Cip7ACOshUI4smpCQanqjSY=
    305 253  github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
    306  -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
    307  -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
    308 254  github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
    309 255  github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
    310 256  github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
    311 257  github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
    312 258  github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
    313 259  github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
    314  -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
    315 260  github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
    316 261  github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
    317 262  github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
    skipped 1 lines
    319 264  github.com/kyokomi/emoji v2.2.4+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
    320 265  github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
    321 266  github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
    322  -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
    323  -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
    324  -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
    325  -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
    326 267  github.com/linode/linodego v1.9.3 h1:+lxNZw4avRxhCqGjwfPgQ2PvMT+vOL0OMsTdzixR7hQ=
    327 268  github.com/linode/linodego v1.9.3/go.mod h1:h6AuFR/JpqwwM/vkj7s8KV3iGN8/jxn+zc437F8SZ8w=
    328 269  github.com/mackerelio/go-osstat v0.2.3 h1:jAMXD5erlDE39kdX2CU7YwCGRcxIO33u/p8+Fhe5dJw=
    skipped 4 lines
    333 274  github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
    334 275  github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
    335 276  github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
    336  -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
    337  -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
    338 277  github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
    339 278  github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
    340 279  github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
    341  -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
    342  -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
    343 280  github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
    344 281  github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
    345 282  github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
    skipped 1 lines
    347 284  github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
    348 285  github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
    349 286  github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
    350  -github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
    351  -github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
    352 287  github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
    353 288  github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
    354 289  github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
    355 290  github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
     291 +github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE=
    356 292  github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
    357 293  github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
    358 294  github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
    skipped 5 lines
    364 300  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
    365 301  github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
    366 302  github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
    367  -github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
    368 303  github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
    369 304  github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
    370 305  github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
    skipped 10 lines
    381 316  github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
    382 317  github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
    383 318  github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
    384  -github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
    385 319  github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
    386  -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
    387 320  github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
    388 321  github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
    389 322  github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
    skipped 2 lines
    392 325  github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
    393 326  github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
    394 327  github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
    395  -github.com/robertkrimen/otto v0.0.0-20221025135307-511d75fba9f8 h1:qD3uiYZ9HFRMIkjcmA5MnB3QxDQmf/r8TfoOx8BMtQ4=
    396  -github.com/robertkrimen/otto v0.0.0-20221025135307-511d75fba9f8/go.mod h1:nuq0maJQz2rTj3sA9EtJleKkkP0QIihFANdtAgTvmyc=
     328 +github.com/robertkrimen/otto v0.2.1 h1:FVP0PJ0AHIjC+N4pKCG9yCDz6LHNPCwi/GKID5pGGF0=
     329 +github.com/robertkrimen/otto v0.2.1/go.mod h1:UPwtJ1Xu7JrLcZjNWN8orJaM5n5YEtqL//farB5FlRY=
    397 330  github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
    398 331  github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
    399 332  github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
    400 333  github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
    401 334  github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
    402  -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
    403  -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
    404  -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
    405 335  github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
    406  -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
    407 336  github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
    408 337  github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
    409  -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
    410  -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
    411  -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
    412  -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
    413 338  github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
    414 339  github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
    415  -github.com/slack-go/slack v0.11.4 h1:ojSa7KlPm3PqY2AomX4VTxEsK5eci5JaxCjlzGV5zoM=
    416  -github.com/slack-go/slack v0.11.4/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
     340 +github.com/slack-go/slack v0.12.0 h1:k93w2dvYXIUO/ggxpz/3ichCpBuCVXxxEAsRqM87np4=
     341 +github.com/slack-go/slack v0.12.0/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw=
    417 342  github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
    418 343  github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
    419 344  github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg=
    skipped 11 lines
    431 356  github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU=
    432 357  github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As=
    433 358  github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
    434  -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
    435  -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
    436 359  github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
    437 360  github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
    438 361  github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
    skipped 6 lines
    445 368  github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
    446 369  github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
    447 370  github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
    448  -github.com/swaggo/swag v1.8.7 h1:2K9ivTD3teEO+2fXV6zrZKDqk5IuU2aJtBDo8U7omWU=
    449  -github.com/swaggo/swag v1.8.7/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9enSk=
     371 +github.com/swaggo/swag v1.8.9 h1:kHtaBe/Ob9AZzAANfcn5c6RyCke9gG9QpH0jky0I/sA=
     372 +github.com/swaggo/swag v1.8.9/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9enSk=
    450 373  github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
    451 374  github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
    452 375  github.com/thoas/go-funk v0.9.2 h1:oKlNYv0AY5nyf9g+/GhMgS/UO2ces0QRdPKwkhY3VCk=
    skipped 11 lines
    464 387  github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
    465 388  github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg=
    466 389  github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
    467  -github.com/xanzy/go-gitlab v0.75.0 h1:U7ywGhvW+qdywQQ+lGJwGK93odDwkX81N5meh6EjaUc=
    468  -github.com/xanzy/go-gitlab v0.75.0/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
     390 +github.com/xanzy/go-gitlab v0.77.0 h1:UrbGlxkWVCbkpa6Fk6cM8ARh+rLACWemkJnsawT7t98=
     391 +github.com/xanzy/go-gitlab v0.77.0/go.mod h1:d/a0vswScO7Agg1CZNz15Ic6SSvBG9vfw8egL99t4kA=
    469 392  github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    470 393  github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    471 394  github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
    472 395  github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
     396 +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
    473 397  github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
    474 398  github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
    475  -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
    476 399  go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
    477 400  go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
    478 401  go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
    479 402  go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
    480 403  go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
    481 404  go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
    482  -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
    483  -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
    484  -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
    485  -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
    486  -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
    487  -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
    488  -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
    489  -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
    490  -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
    491  -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
    492  -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
    493 405  golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
    494  -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
    495 406  golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    496 407  golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    497  -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    498 408  golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
    499 409  golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
    500  -golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
    501  -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
    502 410  golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
    503 411  golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
    504  -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
    505  -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
    506 412  golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
    507 413  golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
    508 414  golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
    509 415  golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
    510  -golang.org/x/crypto v0.3.0 h1:a06MkbcxBrEFc0w0QIZWXrH/9cCX6KJyWbBOIwAn+7A=
    511  -golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
     416 +golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
     417 +golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
    512 418  golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
    513 419  golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
    514 420  golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
    skipped 28 lines
    543 449  golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    544 450  golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    545 451  golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
     452 +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
    546 453  golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    547 454  golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    548 455  golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
    skipped 7 lines
    556 463  golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    557 464  golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    558 465  golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    559  -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    560 466  golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    561 467  golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    562 468  golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
    skipped 15 lines
    578 484  golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
    579 485  golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
    580 486  golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
    581  -golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
    582 487  golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
    583 488  golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
     489 +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
    584 490  golang.org/x/net v0.0.0-20220906165146-f3363e06e74c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
    585  -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
    586  -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
     491 +golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
     492 +golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
     493 +golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
    587 494  golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
    588 495  golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
    589 496  golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
    skipped 3 lines
    593 500  golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
    594 501  golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
    595 502  golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
    596  -golang.org/x/oauth2 v0.2.0 h1:GtQkldQ9m7yvzCL1V+LrYow3Khe0eJH0w7RbX/VbaIU=
    597  -golang.org/x/oauth2 v0.2.0/go.mod h1:Cwn6afJ8jrQwYMxQDTpISoXmXW9I6qF6vDeuuoX3Ibs=
     503 +golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
     504 +golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
    598 505  golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    599 506  golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    600 507  golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    skipped 4 lines
    605 512  golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    606 513  golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    607 514  golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
     515 +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    608 516  golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    609  -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    610 517  golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    611 518  golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    612  -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    613 519  golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    614  -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    615 520  golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    616  -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    617 521  golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    618 522  golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    619 523  golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    620 524  golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    621 525  golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    622  -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    623 526  golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    624 527  golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    625  -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    626 528  golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    627 529  golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    628 530  golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    skipped 24 lines
    653 555  golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    654 556  golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    655 557  golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
     558 +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    656 559  golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
     560 +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    657 561  golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    658 562  golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    659 563  golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    660  -golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
     564 +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    661 565  golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    662  -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
     566 +golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
     567 +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
    663 568  golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
    664 569  golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
    665  -golang.org/x/term v0.2.0 h1:z85xZCsEl7bi/KwbNADeBYoOP0++7W1ipu+aGnpwzRM=
    666  -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
     570 +golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
     571 +golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
     572 +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
    667 573  golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    668 574  golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    669 575  golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
    skipped 2 lines
    672 578  golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    673 579  golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
    674 580  golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
    675  -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
    676 581  golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
     582 +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
     583 +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
    677 584  golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
    678 585  golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
    679 586  golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
    skipped 7 lines
    687 594  golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
    688 595  golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
    689 596  golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
    690  -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
    691 597  golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
    692 598  golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
    693 599  golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
    694 600  golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
    695 601  golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
    696 602  golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    697  -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    698 603  golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    699 604  golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    700  -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    701  -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    702 605  golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    703 606  golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    704 607  golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    skipped 1 lines
    706 609  golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
    707 610  golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
    708 611  golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
    709  -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
    710 612  golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
    711 613  golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
    712 614  golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
    skipped 21 lines
    734 636  golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
    735 637  golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
    736 638  golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
    737  -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    738  -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    739 639  golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    740 640  golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    741 641  golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
    skipped 99 lines
    841 741  gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
    842 742  gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
    843 743  gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
    844  -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
    845 744  gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
    846 745  gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
    847  -gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
    848 746  gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
    849 747  gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
    850 748  gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
    skipped 8 lines
    859 757  gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
    860 758  gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
    861 759  gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
    862  -gorm.io/datatypes v1.0.7 h1:8NhJN4+annFjwV1WufDhFiPjdUvV1lSGUdg1UCjQIWY=
    863  -gorm.io/datatypes v1.0.7/go.mod h1:l9qkCuy0CdzDEop9HKUdcnC9gHC2sRlaFtHkTzsZRqg=
    864  -gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U=
     760 +gorm.io/datatypes v1.1.0 h1:EVp1Z28N4ACpYFK1nHboEIJGIFfjY7vLeieDk8jSHJA=
     761 +gorm.io/datatypes v1.1.0/go.mod h1:SH2K9R+2RMjuX1CkCONrPwoe9JzVv2hkQvEu4bXGojE=
    865 762  gorm.io/driver/mysql v1.4.4 h1:MX0K9Qvy0Na4o7qSC/YI7XxqUw5KDw01umqgID+svdQ=
    866 763  gorm.io/driver/mysql v1.4.4/go.mod h1:BCg8cKI+R0j/rZRQxeKis/forqRwRSYOR8OM3Wo6hOM=
    867  -gorm.io/driver/postgres v1.3.4 h1:evZ7plF+Bp+Lr1mO5NdPvd6M/N98XtwHixGB+y7fdEQ=
    868  -gorm.io/driver/postgres v1.3.4/go.mod h1:y0vEuInFKJtijuSGu9e5bs5hzzSzPK+LancpKpvbRBw=
    869  -gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg=
     764 +gorm.io/driver/postgres v1.4.5 h1:mTeXTTtHAgnS9PgmhN2YeUbazYpLhUI1doLnw42XUZc=
    870 765  gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU=
    871 766  gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
    872  -gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI=
    873  -gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ=
    874  -gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
    875  -gorm.io/gorm v1.23.6/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
     767 +gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0=
    876 768  gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=
    877 769  gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
    878  -gorm.io/gorm v1.24.1 h1:CgvzRniUdG67hBAzsxDGOAuq4Te1osVMYsa1eQbd4fs=
    879  -gorm.io/gorm v1.24.1/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
     770 +gorm.io/gorm v1.24.2 h1:9wR6CFD+G8nOusLdvkZelOEhpJVwwHzpQOUM+REd6U0=
     771 +gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
    880 772  honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
    881 773  honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
    882 774  honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
    skipped 10 lines
  • ■ ■ ■ ■ ■ ■
    libs/mics.go
    skipped 1 lines
    2 2   
    3 3  // Cdn credentials for other client
    4 4  type Cdn struct {
    5  - URL string
    6  - WSURL string
    7  - Prefix string
    8  - Index string
    9  - Auth string
     5 + Bucket string
     6 + Region string
     7 + SecretKey string
     8 + AccessKeyId string
    10 9  }
    11 10   
    12 11  // Git credentials for other client
    skipped 51 lines
  • ■ ■ ■ ■
    libs/version.go
    skipped 3 lines
    4 4   
    5 5  const (
    6 6   // VERSION of this project
    7  - VERSION = "v4.2.0"
     7 + VERSION = "v4.3.0"
    8 8   // DESC description of the tool
    9 9   DESC = "A Workflow Engine for Offensive Security"
    10 10   // BINARY name of osmedeus
    skipped 17 lines
  • ■ ■ ■ ■ ■ ■
    provider/action.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "strings"
     6 + 
    5 7   "github.com/cenkalti/backoff/v4"
     8 + "github.com/fatih/color"
    6 9   "github.com/j3ssie/osmedeus/utils"
    7  - "strings"
     10 + "github.com/spf13/cast"
    8 11  )
    9 12   
    10 13  const (
    skipped 16 lines
    27 30   err = p.GetSSHKeyDO()
    28 31   case "ln", "line", "linode":
    29 32   err = p.GetSSHKeyLN()
     33 + case "aw", "aws", "asw":
     34 + err = p.GetSSHKeyAWS()
    30 35   default:
    31 36   err = p.GetSSHKeyDO()
    32 37   }
    skipped 6 lines
    39 44   err = p.ListInstanceDO()
    40 45   case "ln", "line", "linode":
    41 46   err = p.ListInstanceLN()
     47 + case "aw", "aws", "asw":
     48 + err = p.ListInstanceAWS()
    42 49   default:
    43 50   err = p.ListInstanceDO()
    44 51   }
    skipped 6 lines
    51 58   err = p.ListSnapshotDO()
    52 59   case "ln", "line", "linode":
    53 60   err = p.ListSnapshotLN()
     61 + case "aw", "aws", "asw":
     62 + err = p.ListSnapshotAWS()
    54 63   default:
    55 64   err = p.ListSnapshotDO()
    56 65   }
    skipped 1 lines
    58 67  }
    59 68   
    60 69  func (p *Provider) CreateInstance(name string) (err error) {
    61  - var id int
     70 + var id interface{}
    62 71   operation := func() error {
    63 72   switch p.ProviderName {
    64 73   case "do", "digitalocean":
    skipped 3 lines
    68 77   }
    69 78   case "ln", "line", "linode":
    70 79   id, err = p.CreateInstanceLN(name)
     80 + if err == nil {
     81 + err = p.Action(BootInstance, id)
     82 + err = p.Action(GetInstanceInfo, id)
     83 + }
     84 + 
     85 + case "aw", "aws", "asw":
     86 + id, err = p.CreateInstanceAWS(name)
    71 87   if err == nil {
    72 88   err = p.Action(BootInstance, id)
    73 89   err = p.Action(GetInstanceInfo, id)
    skipped 14 lines
    88 104   return nil
    89 105  }
    90 106   
    91  -func (p *Provider) CreateInstanceF(name string) (err error) {
    92  - var id int
    93  - switch p.ProviderName {
    94  - case "do", "digitalocean":
    95  - id, err = p.CreateInstanceDO(name)
    96  - if err == nil {
    97  - err = p.Action(GetInstanceInfo, id)
    98  - }
    99  - case "ln", "line", "linode":
    100  - id, err = p.CreateInstanceLN(name)
    101  - if err == nil {
    102  - err = p.Action(BootInstance, id)
    103  - err = p.Action(GetInstanceInfo, id)
    104  - }
    105  - default:
    106  - id, err = p.CreateInstanceDO(name)
    107  - if err == nil {
    108  - err = p.Action(GetInstanceInfo, id)
    109  - }
    110  - }
    111  - return err
    112  -}
     107 +// func (p *Provider) CreateInstanceF(name string) (err error) {
     108 +// var id int
     109 +// switch p.ProviderName {
     110 +// case "do", "digitalocean":
     111 +// id, err = p.CreateInstanceDO(name)
     112 +// if err == nil {
     113 +// err = p.Action(GetInstanceInfo, id)
     114 +// }
     115 +// case "ln", "line", "linode":
     116 +// id, err = p.CreateInstanceLN(name)
     117 +// if err == nil {
     118 +// err = p.Action(BootInstance, id)
     119 +// err = p.Action(GetInstanceInfo, id)
     120 +// }
     121 +// default:
     122 +// id, err = p.CreateInstanceDO(name)
     123 +// if err == nil {
     124 +// err = p.Action(GetInstanceInfo, id)
     125 +// }
     126 +// }
     127 +// return err
     128 +// }
    113 129   
    114  -func (p *Provider) BootInstance(id int) (err error) {
     130 +func (p *Provider) BootInstance(id interface{}) (err error) {
    115 131   switch p.ProviderName {
    116 132   case "do", "digitalocean":
    117 133   case "ln", "line", "linode":
    118  - err = p.BootInstanceLN(id)
     134 + err = p.BootInstanceLN(cast.ToInt(id))
     135 + case "aw", "aws", "asw":
     136 + // err = p.AllowRootAccessAWS(cast.ToString(id))
    119 137   default:
    120  - err = p.BootInstanceLN(id)
     138 + err = p.BootInstanceLN(cast.ToInt(id))
    121 139   }
    122 140   if err != nil {
    123 141   utils.WarnF("error booting instance: %v", id)
    skipped 2 lines
    126 144   return nil
    127 145  }
    128 146   
    129  -func (p *Provider) GetInstanceInfo(id int) (err error) {
     147 +func (p *Provider) GetInstanceInfo(id interface{}) (err error) {
    130 148   var instance Instance
    131 149   switch p.ProviderName {
    132 150   case "do", "digitalocean":
    133  - instance, err = p.InstanceInfoDO(id)
     151 + instance, err = p.InstanceInfoDO(cast.ToInt(id))
    134 152   case "ln", "line", "linode":
    135  - instance, err = p.InstanceInfoLN(id)
     153 + instance, err = p.InstanceInfoLN(cast.ToInt(id))
     154 + case "aw", "aws", "asw":
     155 + instance, err = p.InstanceInfoAWS(cast.ToString(id))
    136 156   default:
    137  - instance, err = p.InstanceInfoDO(id)
     157 + instance, err = p.InstanceInfoDO(cast.ToInt(id))
    138 158   }
    139 159   if err != nil {
    140  - utils.WarnF("error getting public IP of instance: %v", instance.InstanceID)
     160 + utils.WarnF("error getting public IP of instance: %v", color.HiBlueString("%v", id))
    141 161   return err
    142 162   }
     163 + p.Instances = append(p.Instances, instance)
    143 164   return nil
    144 165  }
    145 166   
    skipped 4 lines
    150 171   err = p.DeleteInstanceDO(id)
    151 172   case "ln", "line", "linode":
    152 173   err = p.DeleteInstanceLN(id)
     174 + case "aw", "aws", "asw":
     175 + err = p.DeleteInstanceAWS(id)
    153 176   default:
    154 177   err = p.DeleteInstanceDO(id)
    155 178   }
    skipped 7 lines
    163 186   err = p.DeleteSnapShotDO(id)
    164 187   case "ln", "line", "linode":
    165 188   err = p.DeleteSnapShotLN(id)
     189 + case "aw", "aws", "asw":
     190 + err = p.DeleteImageAWS(id)
    166 191   default:
    167 192   err = p.DeleteSnapShotDO(id)
    168 193   }
    skipped 5 lines
  • ■ ■ ■ ■ ■ ■
    provider/building.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
    5  - "github.com/j3ssie/osmedeus/libs"
    6  - "github.com/j3ssie/osmedeus/utils"
    7 5   "os"
    8 6   "path"
    9 7   "strings"
     8 + 
     9 + "github.com/fatih/color"
     10 + "github.com/j3ssie/osmedeus/libs"
     11 + "github.com/j3ssie/osmedeus/utils"
    10 12  )
    11 13   
    12 14  func (p *Provider) PrePareBuildData() {
    skipped 3 lines
    16 18   data := make(map[string]string)
    17 19   data["snapshot_name"] = p.SnapshotName
    18 20   data["api_token"] = p.Token
     21 + // for aws only
     22 + data["access_key"] = p.AccessKeyId
     23 + data["secret_key"] = p.SecretKey
     24 + data["source_ami"] = p.ProviderConfig.DefaultImage
    19 25   
    20 26   // c.Cloud.ProviderFolder --> ~/.osmedeus/provider/<osmp-name>-v4.x-randomstring
    21 27   p.ProviderConfig.ProviderFolder = path.Join(p.Opt.Env.ProviderFolder, fmt.Sprintf("%s-%s", p.SnapshotName, utils.RandomString(6)))
    skipped 86 lines
    108 114   buildFile := path.Join(p.ProviderConfig.ProviderFolder, "build.json")
    109 115   p.ProviderConfig.BuildFile = buildFile
    110 116   utils.WriteToFile(buildFile, buildContent)
    111  - utils.InforF("Write build provision of %s to: %s", p.ProviderName, buildFile)
     117 + utils.InforF("Write build provision of %s to: %s", color.HiYellowString(p.ProviderName), color.HiCyanString(buildFile))
    112 118   
    113 119   // actually run building
    114 120   err = p.Action(RunBuild)
    skipped 19 lines
    134 140   utils.ErrorF(out)
    135 141   return err
    136 142   }
    137  - utils.InforF("Config looks good at: %s", p.ProviderConfig.BuildFile)
     143 + utils.InforF("The Packer file appears to be functioning properly: %s", color.HiCyanString(p.ProviderConfig.BuildFile))
    138 144   
    139 145   // really start to build stuff here
    140  - utils.GoodF("Start packer build for: %s", p.ProviderConfig.BuildFile)
     146 + utils.GoodF("Start packer build for: %s", color.HiCyanString(p.ProviderConfig.BuildFile))
    141 147   cmd = fmt.Sprintf("%s build %s", packerBinary, p.ProviderConfig.BuildFile)
    142 148   out, _ = utils.RunCommandWithErr(cmd)
    143 149   
    skipped 9 lines
  • ■ ■ ■ ■ ■ ■
    provider/parser.go
    1 1  package provider
    2 2   
    3 3  import (
     4 + "io/ioutil"
     5 + 
    4 6   "github.com/Shopify/yaml"
    5 7   "github.com/j3ssie/osmedeus/utils"
    6  - "io/ioutil"
    7 8  )
    8 9   
    9 10  // ConfigProviders cloud config file
    skipped 11 lines
    21 22   
    22 23  type ConfigProvider struct {
    23 24   // core part
    24  - Name string `yaml:"name"`
    25  - Token string `yaml:"token"`
     25 + Name string `yaml:"name"`
     26 + Token string `yaml:"token"`
     27 + 
     28 + SecretKey string `yaml:"secret_key"`
     29 + AccessKeyId string `yaml:"access_key"`
     30 + 
    26 31   Provider string `yaml:"provider"`
    27 32   DefaultImage string `yaml:"default_image"`
    28 33   Size string `yaml:"size"`
    skipped 44 lines
  • ■ ■ ■ ■ ■
    provider/provider.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "strings"
     6 + "time"
     7 + 
    5 8   "github.com/cenkalti/backoff/v4"
    6 9   "github.com/fatih/color"
    7 10   "github.com/j3ssie/osmedeus/libs"
    8 11   "github.com/j3ssie/osmedeus/utils"
    9 12   "github.com/spf13/cast"
    10  - "strings"
    11  - "time"
    12 13  )
    13 14   
    14 15  type Provider struct {
    15 16   ProviderName string
    16 17   Token string
    17 18   RedactedToken string
     19 + // for aws only
     20 + AccessKeyId string
     21 + SecretKey string
     22 + SecurityGroupID string
     23 + SecurityGroupName string
    18 24   
    19 25   Instances []Instance
    20 26   InstanceLimit int
    21 27   Available bool
     28 + HealthCheck bool
    22 29   
    23 30   // for create snapshot
    24 31   SnapshotID string
    skipped 52 lines
    77 84   var provider Provider
    78 85   provider.ProviderName = providerName
    79 86   provider.Token = token
     87 + 
     88 + if providerName == "aws" {
     89 + // token should be 'AccessKeyId,SecretKey'
     90 + provider.AccessKeyId = strings.TrimSpace(strings.Split(token, ",")[0])
     91 + provider.SecretKey = strings.TrimSpace(strings.Split(token, ",")[1])
     92 + provider.Token = token
     93 + }
     94 + 
    80 95   provider.InitClient()
    81 96   return provider, nil
    82 97  }
    skipped 3 lines
    86 101   var provider Provider
    87 102   provider.ProviderName = providerConfig.Provider
    88 103   provider.Token = providerConfig.Token
     104 + 
     105 + // for aws only
     106 + provider.AccessKeyId = providerConfig.AccessKeyId
     107 + provider.SecretKey = providerConfig.SecretKey
     108 + if provider.AccessKeyId != "" {
     109 + provider.Token = provider.AccessKeyId + "," + provider.SecretKey
     110 + }
     111 + 
    89 112   provider.ProviderConfig = providerConfig
    90 113   provider.Opt = opt
    91 114   
    skipped 6 lines
    98 121  }
    99 122   
    100 123  func (p *Provider) InitClient() (err error) {
    101  - if p.Token == "" {
     124 + if p.Token == "" && p.AccessKeyId == "" {
    102 125   utils.ErrorF("empty or invalid token: %v", p.Token)
    103 126   return fmt.Errorf("empty or invalid token")
    104 127   }
    skipped 6 lines
    111 134   switch p.ProviderName {
    112 135   case "do", "digitalocean":
    113 136   p.ClientDO()
     137 + case "ln", "line", "linode":
     138 + p.ClientLinode()
     139 + case "aw", "aws", "asw":
     140 + p.ClientAWS()
     141 + default:
     142 + p.ClientDO()
     143 + }
     144 + 
     145 + // skip balance check if health check
     146 + if p.HealthCheck {
     147 + return nil
     148 + }
     149 + 
     150 + switch p.ProviderName {
     151 + case "do", "digitalocean":
    114 152   err = p.AccountDO()
    115 153   case "ln", "line", "linode":
    116  - p.ClientLinode()
    117 154   err = p.AccountLN()
     155 + case "aw", "aws", "asw":
     156 + err = p.AccountAWS()
    118 157   default:
    119  - p.ClientDO()
    120 158   err = p.AccountDO()
    121 159   }
     160 + 
    122 161   return err
    123 162  }
    124 163   
    skipped 32 lines
    157 196   switch p.ProviderName {
    158 197   case "do", "digitalocean":
    159 198   p.DefaultDO()
    160  - p.Action(GetSSHKey)
    161  - p.Action(ListImage)
    162 199   case "ln", "line", "linode":
    163 200   p.DefaultLinode()
    164  - p.Action(GetSSHKey)
    165  - p.Action(ListImage)
     201 + case "aw", "aws", "asw":
     202 + p.DefaultAWS()
    166 203   default:
    167 204   p.DefaultDO()
    168  - p.Action(GetSSHKey)
    169  - p.Action(ListImage)
    170 205   }
    171 206   
     207 + p.Action(GetSSHKey)
     208 + p.Action(ListImage)
    172 209   if p.SSHKeyID != "" {
    173  - utils.InforF("Found SSH Key ID: %v", p.SSHKeyID)
     210 + utils.InforF("Found SSH Key ID: %v", color.HiBlueString(p.SSHKeyID))
    174 211   }
    175 212  }
    176 213   
    skipped 15 lines
    192 229   case RunBuild:
    193 230   err = p.RunBuild()
    194 231   case GetInstanceInfo:
    195  - err = p.GetInstanceInfo(cast.ToInt(param))
     232 + err = p.GetInstanceInfo(param)
    196 233   case BootInstance:
    197  - err = p.BootInstance(cast.ToInt(param))
     234 + err = p.BootInstance(param)
    198 235   case CreateInstance:
    199 236   err = p.CreateInstance(cast.ToString(param))
    200 237   default:
    skipped 15 lines
  • ■ ■ ■ ■ ■ ■
    provider/provider_aws.go
     1 +package provider
     2 + 
     3 +import (
     4 + "crypto/sha256"
     5 + "encoding/base64"
     6 + "fmt"
     7 + "strings"
     8 + "time"
     9 + 
     10 + "github.com/spf13/cast"
     11 + "golang.org/x/crypto/ssh"
     12 + 
     13 + "github.com/aws/aws-sdk-go/aws"
     14 + "github.com/aws/aws-sdk-go/aws/credentials"
     15 + "github.com/aws/aws-sdk-go/aws/session"
     16 + "github.com/aws/aws-sdk-go/service/costexplorer"
     17 + "github.com/aws/aws-sdk-go/service/ec2"
     18 + "github.com/fatih/color"
     19 + "github.com/j3ssie/osmedeus/libs"
     20 + "github.com/j3ssie/osmedeus/utils"
     21 +)
     22 + 
     23 +// DefaultAWS set some default data for AWS provider
     24 +func (p *Provider) DefaultAWS() {
     25 + p.Region = "ap-southeast-1"
     26 + p.Size = "t2.medium"
     27 + p.SecurityGroupName = "osmp-allow-root-access"
     28 + //p.Image = "ami-073770dc3242b2a06"
     29 + //p.Type = "aws-ebs"
     30 + 
     31 + if p.ProviderConfig.Region != "" {
     32 + p.Region = p.ProviderConfig.Region
     33 + }
     34 + if p.ProviderConfig.Size != "" {
     35 + p.Size = p.ProviderConfig.Size
     36 + }
     37 +}
     38 + 
     39 +func (p *Provider) InitSessionAWS() (*session.Session, error) {
     40 + sess, err := session.NewSession(&aws.Config{
     41 + Region: aws.String(p.Region),
     42 + Credentials: credentials.NewStaticCredentials(p.AccessKeyId, p.SecretKey, ""),
     43 + })
     44 + 
     45 + return sess, err
     46 +}
     47 + 
     48 +func (p *Provider) ClientAWS() {
     49 + client, err := p.InitSessionAWS()
     50 + if err != nil {
     51 + panic(err)
     52 + }
     53 + p.ProviderName = "aws"
     54 + p.Client = client
     55 +}
     56 + 
     57 +func (p *Provider) ConvertClientAWS() *session.Session {
     58 + sess, ok := p.Client.(*session.Session)
     59 + if !ok {
     60 + utils.ErrorF("error converting aws session %v", ok)
     61 + }
     62 + sess.Config.Region = aws.String(p.Region)
     63 + return sess
     64 +}
     65 + 
     66 +func (p *Provider) AccountAWS() error {
     67 + ceSvc := costexplorer.New(p.ConvertClientAWS())
     68 + // Set the parameters for the query
     69 + now := time.Now()
     70 + start := time.Date(now.Year(), now.Month()-1, 1, 0, 0, 0, 0, now.Location())
     71 + end := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
     72 + params := &costexplorer.GetCostAndUsageInput{
     73 + TimePeriod: &costexplorer.DateInterval{
     74 + Start: aws.String(start.Format("2006-01-02")),
     75 + End: aws.String(end.Format("2006-01-02")),
     76 + },
     77 + Granularity: aws.String(costexplorer.GranularityMonthly),
     78 + Metrics: []*string{aws.String("UnblendedCost")},
     79 + }
     80 + 
     81 + // Send the query and get the results
     82 + result, err := ceSvc.GetCostAndUsage(params)
     83 + if err != nil {
     84 + utils.ErrorF("Error getting cost and usage:", err)
     85 + return err
     86 + }
     87 + 
     88 + // Print the total cost for the previous month
     89 + cost := *result.ResultsByTime[0].Total["UnblendedCost"].Amount
     90 + utils.InforF("The total cost of AWS services for the this month was %s", color.HiRedString("$"+cost))
     91 + return nil
     92 +}
     93 + 
     94 +func (p *Provider) GetSSHKeyAWS() error {
     95 + ec2Svc := ec2.New(p.ConvertClientAWS())
     96 + // Get a list of all the key pairs in the account
     97 + keyPairsOutput, err := ec2Svc.DescribeKeyPairs(&ec2.DescribeKeyPairsInput{})
     98 + if err != nil {
     99 + utils.ErrorF("Error describing key pairs: %v", err)
     100 + return err
     101 + }
     102 + 
     103 + pubKeyBytes := []byte(p.SSHPublicKey)
     104 + // Parse the key, other info ignored
     105 + pubKey, _, _, _, err := ssh.ParseAuthorizedKey(pubKeyBytes)
     106 + if err != nil {
     107 + utils.ErrorF("%v", err)
     108 + return err
     109 + }
     110 + hash := sha256.Sum256(pubKey.Marshal())
     111 + sshHash := base64.StdEncoding.EncodeToString(hash[:])
     112 + 
     113 + // Check if your SSH key is present in the list
     114 + for _, keyPair := range keyPairsOutput.KeyPairs {
     115 + // found the same key name but different key fingerprint
     116 + if *keyPair.KeyName == p.SSHKeyName && *keyPair.KeyFingerprint != sshHash {
     117 + // Delete the key pair
     118 + _, err := ec2Svc.DeleteKeyPair(&ec2.DeleteKeyPairInput{
     119 + KeyName: aws.String(*keyPair.KeyName),
     120 + })
     121 + if err != nil {
     122 + utils.ErrorF("%v", err)
     123 + }
     124 + utils.InforF("Successfully deleted key pair %s", color.HiBlueString(*keyPair.KeyName))
     125 + }
     126 + 
     127 + if *keyPair.KeyFingerprint == sshHash {
     128 + p.SSHKeyID = cast.ToString(*keyPair.KeyPairId)
     129 + p.SSHKeyFound = true
     130 + break
     131 + }
     132 + 
     133 + }
     134 + 
     135 + if p.SSHKeyFound {
     136 + utils.DebugF("Your SSH key was found in the account: %v -- %v", color.HiCyanString(p.SSHKeyName), color.HiCyanString(p.SSHKeyID))
     137 + return nil
     138 + }
     139 + 
     140 + // Import the SSH key into your AWS account
     141 + result, err := ec2Svc.ImportKeyPair(&ec2.ImportKeyPairInput{
     142 + KeyName: aws.String(p.SSHKeyName),
     143 + PublicKeyMaterial: []byte(p.SSHPublicKey),
     144 + })
     145 + if err != nil {
     146 + utils.ErrorF("Error create key pairs: %v", err)
     147 + return err
     148 + }
     149 + utils.DebugF("Successfully imported SSH key: %v -- %v", color.HiCyanString(*result.KeyName), color.HiCyanString(*result.KeyPairId))
     150 + p.SSHKeyID = cast.ToString(*result.KeyPairId)
     151 + p.SSHKeyFound = true
     152 + 
     153 + return nil
     154 +}
     155 + 
     156 +func (p *Provider) ListSnapshotAWS() error {
     157 + svc := ec2.New(p.ConvertClientAWS())
     158 + 
     159 + // listing only image that own by you
     160 + self := "self"
     161 + ownImages := &ec2.DescribeImagesInput{Owners: []*string{&self}}
     162 + result, err := svc.DescribeImages(ownImages)
     163 + if err != nil {
     164 + utils.ErrorF("err: Unable to list images, %v", err)
     165 + return err
     166 + }
     167 + 
     168 + for _, item := range result.Images {
     169 + if strings.HasPrefix(*item.Name, libs.SNAPSHOT) {
     170 + p.OldSnapShotID = append(p.OldSnapShotID, *item.ImageId)
     171 + }
     172 + 
     173 + if strings.TrimSpace(*item.Name) == strings.TrimSpace(p.SnapshotName) {
     174 + utils.InforF("Found base image snapshot with ID: %s", color.HiBlueString(*item.ImageId))
     175 + p.SnapshotID = *item.ImageId
     176 + p.SnapshotName = *item.Name
     177 + p.SnapshotFound = true
     178 + }
     179 + }
     180 + 
     181 + return nil
     182 +}
     183 + 
     184 +func (p *Provider) DeleteImageAWS(id string) error {
     185 + if p.SnapshotID == "" {
     186 + return nil
     187 + }
     188 + svc := ec2.New(p.ConvertClientAWS())
     189 + deletedImage := &ec2.DeregisterImageInput{ImageId: &p.SnapshotID}
     190 + _, err := svc.DeregisterImage(deletedImage)
     191 + if err != nil {
     192 + utils.ErrorF("err: Unable to delete snapshot: %v -- %v", id, err)
     193 + return err
     194 + }
     195 + utils.InforF("Deleted image ID: %v", color.HiRedString(p.SnapshotID))
     196 + p.DeleteSnapshotAWS()
     197 + return nil
     198 +}
     199 + 
     200 +func (p *Provider) DeleteSnapshotAWS() error {
     201 + svc := ec2.New(p.ConvertClientAWS())
     202 + 
     203 + // List all snapshots
     204 + result, err := svc.DescribeSnapshots(&ec2.DescribeSnapshotsInput{
     205 + OwnerIds: []*string{aws.String("self")},
     206 + MaxResults: aws.Int64(1000),
     207 + })
     208 + if err != nil {
     209 + utils.ErrorF("Error listing snapshots: %v", err)
     210 + return err
     211 + }
     212 + 
     213 + var snapshotIDs []string
     214 + for _, snapshot := range result.Snapshots {
     215 + 
     216 + for _, tag := range snapshot.Tags {
     217 + if *tag.Key == "Name" && *tag.Value == "Osmedeus Premium Image" {
     218 + snapshotIDs = append(snapshotIDs, *snapshot.SnapshotId)
     219 + }
     220 + }
     221 + }
     222 + 
     223 + for _, snapshotID := range snapshotIDs {
     224 + _, err = svc.DeleteSnapshot(&ec2.DeleteSnapshotInput{
     225 + SnapshotId: aws.String(snapshotID),
     226 + })
     227 + if err != nil {
     228 + utils.ErrorF("Error deleting snapshot: %v -- %v", snapshotID, err)
     229 + } else {
     230 + utils.DebugF("Delted snapshot ID: %v", color.HiRedString(snapshotID))
     231 + }
     232 + }
     233 + 
     234 + return nil
     235 +}
     236 + 
     237 +func (p *Provider) ListInstanceAWS() error {
     238 + svc := ec2.New(p.ConvertClientAWS())
     239 + result, err := svc.DescribeInstances(nil)
     240 + if err != nil {
     241 + utils.ErrorF("err: Unable to list ec2 instances: %v", err)
     242 + return err
     243 + }
     244 + 
     245 + var numberOfInstance int
     246 + for i := range result.Reservations {
     247 + for _, instance := range result.Reservations[i].Instances {
     248 + if *instance.State.Name != "running" {
     249 + continue
     250 + }
     251 + numberOfInstance += 1
     252 + 
     253 + launchTime := *instance.LaunchTime
     254 + creationDate := launchTime.Format(time.RFC1123)
     255 + parsedInstance := Instance{
     256 + InstanceID: cast.ToString(*instance.InstanceId),
     257 + IPAddress: *instance.PublicIpAddress,
     258 + InstanceName: *instance.State.Name,
     259 + ImageID: cast.ToString(*instance.ImageId),
     260 + // ImageName: instance.Image.Name,
     261 + // Region: instance.Region.Slug,
     262 + // Region: *instance.Architecture,
     263 + // Memory: cast.ToString(instance.Memory),
     264 + // CPU: cast.ToString(instance.Vcpus),
     265 + // Disk: cast.ToString(instance.Disk),
     266 + Status: *instance.State.Name,
     267 + CreatedAt: cast.ToString(creationDate),
     268 + InputName: "",
     269 + ProviderName: "aws",
     270 + }
     271 + 
     272 + p.Instances = append(p.Instances, parsedInstance)
     273 + }
     274 + }
     275 + 
     276 + utils.InforF("Found %v running instances", color.HiMagentaString("%v", numberOfInstance))
     277 + // check if we reach max instance number
     278 + if p.InstanceLimit > 0 {
     279 + if len(p.Instances) >= p.InstanceLimit {
     280 + p.Available = false
     281 + }
     282 + }
     283 + 
     284 + return nil
     285 +}
     286 + 
     287 +func (p *Provider) CreateInstanceAWS(InstanceName string) (instanctID string, err error) {
     288 + svc := ec2.New(p.ConvertClientAWS())
     289 + p.CreateSecurityGroup()
     290 + 
     291 + // Set the parameters for the instance
     292 + params := &ec2.RunInstancesInput{
     293 + // InstanceName: aws.String(name),
     294 + ImageId: aws.String(p.SnapshotID), // Replace with the ID of the image you want to use
     295 + InstanceType: aws.String(p.Size), // Specify the instance type like t2.micro
     296 + MinCount: aws.Int64(1),
     297 + MaxCount: aws.Int64(1),
     298 + KeyName: aws.String(p.SSHKeyName),
     299 + SecurityGroups: []*string{
     300 + aws.String(p.SecurityGroupName),
     301 + },
     302 + TagSpecifications: []*ec2.TagSpecification{
     303 + {
     304 + ResourceType: aws.String("instance"),
     305 + Tags: []*ec2.Tag{
     306 + {
     307 + Key: aws.String("Name"),
     308 + Value: aws.String(InstanceName),
     309 + },
     310 + },
     311 + },
     312 + },
     313 + }
     314 + 
     315 + // Create the instance
     316 + result, err := svc.RunInstances(params)
     317 + if err != nil {
     318 + utils.ErrorF("Error creating instance: %v", err)
     319 + return
     320 + }
     321 + 
     322 + // Get the instance ID
     323 + instanctID = *result.Instances[0].InstanceId
     324 + utils.InforF("Successfully Created Instance ID: %v -- %v", color.HiBlueString(instanctID), color.HiBlueString(InstanceName))
     325 + utils.DebugF("Waiting for the instance %v to be ready...", color.HiBlueString(instanctID))
     326 + 
     327 + time.Sleep(60 * time.Second)
     328 + // Get the instance state
     329 + for i := 0; i < 10; i++ {
     330 + if p.InstanceReady(instanctID) == nil {
     331 + return instanctID, nil
     332 + }
     333 + time.Sleep(60 * time.Second)
     334 + }
     335 + 
     336 + return instanctID, nil
     337 +}
     338 + 
     339 +func (p *Provider) InstanceReady(instanceID string) error {
     340 + svc := ec2.New(p.ConvertClientAWS())
     341 + 
     342 + // Describe the instance
     343 + params := &ec2.DescribeInstancesInput{
     344 + InstanceIds: []*string{
     345 + aws.String(instanceID),
     346 + },
     347 + }
     348 + _, err := svc.DescribeInstances(params)
     349 + if err != nil {
     350 + return err
     351 + }
     352 + 
     353 + return nil
     354 +}
     355 + 
     356 +func (p *Provider) InstanceReboot(instanceID string) error {
     357 + svc := ec2.New(p.ConvertClientAWS())
     358 + 
     359 + // Create the input for the RebootInstances operation
     360 + params := &ec2.RebootInstancesInput{
     361 + InstanceIds: []*string{aws.String(instanceID)},
     362 + }
     363 + 
     364 + // Call the RebootInstances operation
     365 + _, err := svc.RebootInstances(params)
     366 + if err != nil {
     367 + fmt.Println("Error rebooting instance:", err)
     368 + return err
     369 + }
     370 + return nil
     371 +}
     372 + 
     373 +func (p *Provider) DeleteInstanceAWS(id string) error {
     374 + svc := ec2.New(p.ConvertClientAWS())
     375 + 
     376 + // Set the parameters for the instance
     377 + params := &ec2.TerminateInstancesInput{
     378 + InstanceIds: []*string{
     379 + aws.String(id), // Replace with the ID of the instance you want to delete
     380 + },
     381 + }
     382 + 
     383 + // Delete the instance
     384 + _, err := svc.TerminateInstances(params)
     385 + if err != nil {
     386 + utils.ErrorF("Error deleting instance: %v", err)
     387 + return err
     388 + }
     389 + 
     390 + utils.InforF("Successfully Deleted instance ID: %v", color.HiRedString(id))
     391 + return nil
     392 +}
     393 + 
     394 +func (p *Provider) InstanceInfoAWS(id string) (Instance, error) {
     395 + var parsedInstance Instance
     396 + 
     397 + svc := ec2.New(p.ConvertClientAWS())
     398 + 
     399 + // Set the parameters for the instance
     400 + params := &ec2.DescribeInstancesInput{
     401 + InstanceIds: []*string{
     402 + aws.String(id),
     403 + },
     404 + }
     405 + 
     406 + // Get the instance information
     407 + result, err := svc.DescribeInstances(params)
     408 + if err != nil {
     409 + utils.ErrorF("Error getting instance information: %v", err)
     410 + return parsedInstance, err
     411 + }
     412 + 
     413 + // Print the instance information
     414 + for _, reservation := range result.Reservations {
     415 + for _, instance := range reservation.Instances {
     416 + 
     417 + launchTime := *instance.LaunchTime
     418 + creationDate := launchTime.Format(time.RFC1123)
     419 + 
     420 + var instanceName string
     421 + for _, tag := range instance.Tags {
     422 + if *tag.Key == "Name" {
     423 + instanceName = *tag.Value
     424 + break
     425 + }
     426 + }
     427 + 
     428 + parsedInstance = Instance{
     429 + InstanceID: cast.ToString(*instance.InstanceId),
     430 + IPAddress: *instance.PublicIpAddress,
     431 + InstanceName: instanceName,
     432 + ImageID: cast.ToString(*instance.ImageId),
     433 + Status: *instance.State.Name,
     434 + CreatedAt: cast.ToString(creationDate),
     435 + InputName: "",
     436 + ProviderName: "aws",
     437 + }
     438 + 
     439 + }
     440 + }
     441 + 
     442 + p.CreatedInstance = parsedInstance
     443 + utils.DebugF("Instance ID Info: %v -- %v -- %v", color.HiBlueString(p.CreatedInstance.InstanceID), p.CreatedInstance.InstanceName, p.CreatedInstance.IPAddress)
     444 + return parsedInstance, nil
     445 +}
     446 + 
     447 +func (p *Provider) CreateSecurityGroup() error {
     448 + svc := ec2.New(p.ConvertClientAWS())
     449 + 
     450 + // Set the parameters for the security group
     451 + params := &ec2.DescribeSecurityGroupsInput{
     452 + GroupNames: []*string{
     453 + aws.String(p.SecurityGroupName), // Replace with the ID of the security group you want to check
     454 + },
     455 + }
     456 + 
     457 + // Get the security group information
     458 + scGroups, err := svc.DescribeSecurityGroups(params)
     459 + if err == nil {
     460 + // Print the security group information
     461 + for _, group := range scGroups.SecurityGroups {
     462 + if *group.GroupName == p.SecurityGroupName {
     463 + p.SecurityGroupID = *group.GroupId
     464 + utils.DebugF("Security Group allow root access has been found: %v", color.HiBlueString(p.SecurityGroupID))
     465 + return nil
     466 + }
     467 + }
     468 + }
     469 + 
     470 + // only create if not found
     471 + 
     472 + // Create the security group
     473 + result, err := svc.CreateSecurityGroup(&ec2.CreateSecurityGroupInput{
     474 + GroupName: aws.String("osmp-allow-root-access"),
     475 + Description: aws.String("Security group for allowing root access to EC2 instances"),
     476 + })
     477 + if err != nil {
     478 + utils.ErrorF("Error creating security group: %v", err)
     479 + return err
     480 + }
     481 + 
     482 + // Add a rule to the security group to allow SSH access from any IP address
     483 + _, err = svc.AuthorizeSecurityGroupIngress(&ec2.AuthorizeSecurityGroupIngressInput{
     484 + GroupId: aws.String(*result.GroupId),
     485 + IpPermissions: []*ec2.IpPermission{
     486 + {
     487 + FromPort: aws.Int64(22),
     488 + ToPort: aws.Int64(22),
     489 + IpProtocol: aws.String("tcp"),
     490 + IpRanges: []*ec2.IpRange{
     491 + {CidrIp: aws.String("0.0.0.0/0")},
     492 + },
     493 + },
     494 + },
     495 + })
     496 + if err != nil {
     497 + utils.ErrorF("Error adding rule to security group: %v", err)
     498 + return err
     499 + }
     500 + 
     501 + p.SecurityGroupID = *result.GroupId
     502 + utils.DebugF("Security Group allow root access has been found: %v", color.HiBlueString(p.SecurityGroupID))
     503 + return nil
     504 +}
     505 + 
  • ■ ■ ■ ■ ■ ■
    provider/provider_digitalocean.go
    skipped 31 lines
    32 32   p.Client = client
    33 33  }
    34 34   
    35  -func (p *Provider) AccountDO() error {
     35 +func (p *Provider) ConvertClientDO() *godo.Client {
    36 36   client, ok := p.Client.(*godo.Client)
    37 37   if !ok {
    38  - return fmt.Errorf("error convert client")
     38 + utils.ErrorF("error converting digital ocean session %v", ok)
    39 39   }
     40 + return client
     41 +}
     42 + 
     43 +func (p *Provider) AccountDO() error {
     44 + client := p.ConvertClientDO()
    40 45   ctx := context.TODO()
    41 46   
    42 47   account, _, err := client.Account.Get(ctx)
    skipped 12 lines
    55 60  }
    56 61   
    57 62  func (p *Provider) ListInstanceDO() error {
    58  - client, ok := p.Client.(*godo.Client)
    59  - if !ok {
    60  - return fmt.Errorf("error convert client")
    61  - }
     63 + client := p.ConvertClientDO()
    62 64   
    63 65   ctx := context.TODO()
    64 66   opt := &godo.ListOptions{
    skipped 41 lines
    106 108   }
    107 109   
    108 110   return nil
    109  - 
    110 111  }
    111 112   
    112 113  func (p *Provider) GetSSHKeyDO() error {
    113  - client, ok := p.Client.(*godo.Client)
    114  - if !ok {
    115  - return fmt.Errorf("error convert client")
    116  - }
     114 + client := p.ConvertClientDO()
    117 115   
    118 116   ctx := context.TODO()
    119 117   opt := &godo.ListOptions{
    skipped 6 lines
    126 124   return fmt.Errorf("error listing ssh key -- %v", err)
    127 125   }
    128 126   
    129  - //utils.DebugF("Looking for key: %v", p.SSHPublicKey)
    130 127   for _, key := range keys {
    131  - //utils.DebugF("SSH Key: %v -- %v", key.ID, key.PublicKey)
    132 128   if strings.TrimSpace(key.PublicKey) == strings.TrimSpace(p.SSHPublicKey) {
    133 129   p.SSHKeyID = cast.ToString(key.ID)
    134 130   p.SSHKeyFound = true
    skipped 22 lines
    157 153  }
    158 154   
    159 155  func (p *Provider) ListSnapshotDO() error {
    160  - client, ok := p.Client.(*godo.Client)
    161  - if !ok {
    162  - utils.ErrorF("error convert client")
    163  - return fmt.Errorf("error convert client")
    164  - }
     156 + client := p.ConvertClientDO()
    165 157   
    166 158   ctx := context.TODO()
    167 159   opt := &godo.ListOptions{
    skipped 15 lines
    183 175   }
    184 176   
    185 177   if strings.TrimSpace(name) == strings.TrimSpace(p.SnapshotName) {
    186  - utils.InforF("Found base image snapshot with ID: %s", id)
     178 + utils.InforF("Found base image snapshot with ID: %s", color.HiBlueString(id))
    187 179   p.SnapshotID = id
    188 180   p.SnapshotName = name
    189 181   p.SnapshotFound = true
    skipped 5 lines
    195 187  }
    196 188   
    197 189  func (p *Provider) CreateInstanceDO(name string) (dropletId int, err error) {
    198  - client, ok := p.Client.(*godo.Client)
    199  - if !ok {
    200  - utils.ErrorF("error convert client")
    201  - return dropletId, fmt.Errorf("error convert client")
    202  - }
     190 + client := p.ConvertClientDO()
    203 191   
    204 192   ctx := context.TODO()
    205 193   createRequest := &godo.DropletCreateRequest{
    skipped 22 lines
    228 216   
    229 217   // get droplet IP info
    230 218   dropletId = instance.ID
    231  - time.Sleep(60 * time.Second)
     219 + utils.DebugF("Created instance %v", color.HiBlueString("%v", instance.ID))
     220 + utils.DebugF("Waiting for the instance %v to be ready...", color.HiBlueString("%v", instance.ID))
     221 + time.Sleep(100 * time.Second)
    232 222   return dropletId, nil
    233 223  }
    234 224   
    235 225  func (p *Provider) InstanceInfoDO(id int) (Instance, error) {
    236 226   var parsedInstance Instance
    237  - client, ok := p.Client.(*godo.Client)
    238  - if !ok {
    239  - utils.ErrorF("error convert client")
    240  - return parsedInstance, fmt.Errorf("error convert client")
    241  - }
     227 + client := p.ConvertClientDO()
    242 228   ctx := context.TODO()
    243 229   instance, _, err := client.Droplets.Get(ctx, id)
    244 230   if err != nil {
    245  - return parsedInstance, fmt.Errorf("error get instance info")
     231 + return parsedInstance, fmt.Errorf("error get instance info:")
    246 232   }
    247 233   
    248 234   ipAddress, err := instance.PublicIPv4()
    skipped 17 lines
    266 252   ProviderName: "do",
    267 253   }
    268 254   p.CreatedInstance = parsedInstance
    269  - utils.DebugF("Created instance ID: %v -- %v -- %v", p.CreatedInstance.InstanceID, p.CreatedInstance.InstanceName, p.CreatedInstance.IPAddress)
     255 + utils.DebugF("Successfully Created Instance: %v -- %v -- %v", p.CreatedInstance.InstanceID, p.CreatedInstance.InstanceName, p.CreatedInstance.IPAddress)
    270 256   
    271 257   return parsedInstance, nil
    272 258  }
    273 259   
    274 260  func (p *Provider) DeleteInstanceDO(id string) error {
    275  - client, ok := p.Client.(*godo.Client)
    276  - if !ok {
    277  - utils.ErrorF("error convert client")
    278  - return fmt.Errorf("error convert client")
    279  - }
     261 + client := p.ConvertClientDO()
    280 262   ctx := context.TODO()
    281 263   _, err := client.Droplets.Delete(ctx, cast.ToInt(id))
    282 264   if err != nil {
    283 265   utils.ErrorF("error delete instance -- %v", err)
    284 266   return fmt.Errorf("error delete instance")
    285 267   }
    286  - utils.InforF("Deleted instance ID: %v", color.HiRedString(id))
     268 + utils.InforF("Successfully Deleted instance ID: %v", color.HiRedString(id))
    287 269   return nil
    288 270  }
    289 271   
    290 272  func (p *Provider) DeleteSnapShotDO(id string) error {
    291  - client, ok := p.Client.(*godo.Client)
    292  - if !ok {
    293  - utils.ErrorF("error convert client")
    294  - return fmt.Errorf("error convert client")
    295  - }
     273 + client := p.ConvertClientDO()
    296 274   ctx := context.TODO()
    297 275   
    298 276   _, err := client.Snapshots.Delete(ctx, id)
    skipped 8 lines
  • ■ ■ ■ ■ ■ ■
    provider/provider_linode.go
    skipped 3 lines
    4 4   "context"
    5 5   "encoding/json"
    6 6   "fmt"
     7 + "log"
     8 + "net/http"
     9 + "strings"
     10 + "time"
     11 + 
    7 12   "github.com/fatih/color"
    8 13   "github.com/j3ssie/osmedeus/libs"
    9 14   "github.com/j3ssie/osmedeus/utils"
    10 15   "github.com/linode/linodego"
    11  - //"github.com/linode/linodego/pkg/errors"
    12 16   "github.com/spf13/cast"
    13 17   "golang.org/x/oauth2"
    14  - "log"
    15  - "net/http"
    16  - "strings"
    17  - "time"
    18 18  )
    19 19   
    20 20  // DefaultLinode set some default data for DO provider
    skipped 31 lines
    52 52   return nil
    53 53  }
    54 54   
    55  -func (p *Provider) AccountLN() error {
     55 +func (p *Provider) ConvertClientLinode() linodego.Client {
    56 56   client, ok := p.Client.(linodego.Client)
    57 57   if !ok {
    58  - err := fmt.Errorf("error convert client")
    59  - utils.ErrorF("%v", err)
    60  - return err
     58 + utils.ErrorF("error converting linode session %v", ok)
    61 59   }
     60 + return client
     61 +}
     62 + 
     63 +func (p *Provider) AccountLN() error {
     64 + client := p.ConvertClientLinode()
    62 65   ctx := context.TODO()
    63 66   account, err := client.GetAccount(ctx)
    64 67   if err != nil {
    skipped 1 lines
    66 69   }
    67 70   utils.InforF("Account Billing Information: BalanceUninvoiced: %v -- AccountBalance: %v", color.HiRedString("%v", account.BalanceUninvoiced), color.HiGreenString("%v", account.Balance))
    68 71   
    69  - //accountSett, err := client.GetAccountSettings(ctx)
    70  - //if err != nil {
    71  - // //err := fmt.Errorf("error convert client")
    72  - // utils.ErrorF("%v", err)
    73  - // return err
    74  - //}
    75  - //if err != nil && accountSett.NetworkHelper == false {
    76 72   helper := false
    77 73   opt := linodego.AccountSettingsUpdateOptions{
    78 74   NetworkHelper: &helper,
    skipped 15 lines
    94 90   
    95 91  // LinodeTest list all instances
    96 92  func (p *Provider) LinodeTest() error {
    97  - linodeClient, ok := p.Client.(linodego.Client)
    98  - if !ok {
    99  - return fmt.Errorf("error convert client")
    100  - }
     93 + linodeClient := p.ConvertClientLinode()
    101 94   
    102 95   res, err := linodeClient.GetInstance(context.Background(), 4090913)
    103 96   if err != nil {
    skipped 5 lines
    109 102  }
    110 103   
    111 104  func (p *Provider) ListInstanceLN() error {
    112  - client, ok := p.Client.(linodego.Client)
    113  - if !ok {
    114  - return fmt.Errorf("error convert client")
    115  - }
     105 + client := p.ConvertClientLinode()
    116 106   
    117 107   opt := &linodego.ListOptions{
    118 108   PageOptions: nil,
    skipped 36 lines
    155 145  }
    156 146   
    157 147  func (p *Provider) GetSSHKeyLN() error {
    158  - client, ok := p.Client.(linodego.Client)
    159  - if !ok {
    160  - return fmt.Errorf("error convert client")
    161  - }
     148 + client := p.ConvertClientLinode()
    162 149   ctx := context.TODO()
    163 150   opt := &linodego.ListOptions{
    164 151   PageOptions: nil,
    skipped 32 lines
    197 184  }
    198 185   
    199 186  func (p *Provider) ListSnapshotLN() error {
    200  - client, ok := p.Client.(linodego.Client)
    201  - if !ok {
    202  - return fmt.Errorf("error convert client")
    203  - }
     187 + client := p.ConvertClientLinode()
    204 188   ctx := context.TODO()
    205 189   opt := &linodego.ListOptions{
    206 190   //PageOptions: linodego.PageOptions{
    skipped 37 lines
    244 228  }
    245 229   
    246 230  func (p *Provider) CreateInstanceLN(name string) (dropletId int, err error) {
    247  - client, ok := p.Client.(linodego.Client)
    248  - if !ok {
    249  - return 0, fmt.Errorf("error convert client")
    250  - }
     231 + client := p.ConvertClientLinode()
    251 232   
    252 233   ctx := context.TODO()
    253 234   booted := false
    skipped 9 lines
    263 244   RootPass: utils.RandomString(10),
    264 245   AuthorizedKeys: []string{
    265 246   p.SSHPublicKey,
    266  - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/oKuLLgmqcGK8lf9D2GPZqSXzvE9QqsSPmHdWOybOIYkUzAioG97vcTy6iBiuoRDqRwxeTt7JE/IncfdEc8e7ofa5IoGg5Xx65G1tw/V2rY2yux/IQYV10GVfPlV4Un04z7Vx7oFGcgIcJRxTlyoVPrSCTM1cepp5hAW8eqyF7mJZU/5cWCJMRK7F3CX3p6Li1y0f4dOcMuGvZePQUt4P1ntkrKVijxihiJ0nEfSINee2oKTNM0ZIpoxTmmMIBksMK9Ayl4jgxMf5kPoMQHJM+kTg6IFcarYvKdG2qizqDbjgiORG+2AgWaiAmJb+uik0cNi+gyMNanrxL979yUsj root@j3ssie",
    267 247   },
    268 248   //AuthorizedUsers: []string{"root"},
    269 249   Image: p.SnapshotID,
    skipped 24 lines
    294 274  }
    295 275   
    296 276  func (p *Provider) BootInstanceLN(dropletId int) error {
    297  - client, ok := p.Client.(linodego.Client)
    298  - if !ok {
    299  - return fmt.Errorf("error convert client")
    300  - }
     277 + client := p.ConvertClientLinode()
    301 278   
    302 279   ctx := context.TODO()
    303 280   err := client.BootInstance(ctx, dropletId, 0)
    skipped 1 lines
    305 282  }
    306 283   
    307 284  func (p *Provider) MountDiskLN(dropletId int) error {
    308  - client, ok := p.Client.(linodego.Client)
    309  - if !ok {
    310  - return fmt.Errorf("error convert client")
    311  - }
     285 + client := p.ConvertClientLinode()
    312 286   utils.InforF("Mounting disk: %v", dropletId)
    313  - //err := client.BootInstance(ctx, dropletId, 0)
    314 287   ctx := context.TODO()
    315 288   
    316 289   disk, err := client.CreateInstanceDisk(ctx, dropletId, linodego.InstanceDiskCreateOptions{
    skipped 20 lines
    337 310   
    338 311  func (p *Provider) InstanceInfoLN(id int) (Instance, error) {
    339 312   var parsedInstance Instance
    340  - client, ok := p.Client.(linodego.Client)
    341  - if !ok {
    342  - return parsedInstance, fmt.Errorf("error convert client")
    343  - }
     313 + client := p.ConvertClientLinode()
    344 314   
    345 315   instance, err := client.GetInstance(context.TODO(), id)
    346 316   if err != nil {
    skipped 27 lines
    374 344  }
    375 345   
    376 346  func (p *Provider) DeleteInstanceLN(id string) error {
    377  - client, ok := p.Client.(linodego.Client)
    378  - if !ok {
    379  - return fmt.Errorf("error convert client")
    380  - }
     347 + client := p.ConvertClientLinode()
    381 348   
    382 349   ctx := context.TODO()
    383 350   err := client.DeleteInstance(ctx, cast.ToInt(id))
    skipped 6 lines
    390 357  }
    391 358   
    392 359  func (p *Provider) DeleteSnapShotLN(id string) error {
    393  - client, ok := p.Client.(linodego.Client)
    394  - if !ok {
    395  - return fmt.Errorf("error convert client")
    396  - }
     360 + client := p.ConvertClientLinode()
    397 361   
    398 362   ctx := context.TODO()
    399 363   err := client.DeleteImage(ctx, id)
    skipped 113 lines
  • ■ ■ ■ ■ ■ ■
    provider/provider_test.go
    1 1  package provider
    2 2   
    3 3  import (
     4 + "testing"
     5 + 
    4 6   "github.com/davecgh/go-spew/spew"
    5  - "testing"
    6 7  )
    7 8   
    8 9  var sampleToken = "d17ab13b0a3fccafefc932b9db95be45464339073100423336045977c0924491"
    skipped 75 lines
    84 85   spew.Dump(provider.Instances)
    85 86  }
    86 87   
     88 +func TestProviderAccountAWS(t *testing.T) {
     89 + provider, err := InitProvider("aws", sampleToken)
     90 + if err != nil {
     91 + t.Errorf("error ")
     92 + }
     93 + 
     94 + provider.AccountDO()
     95 +}
     96 + 
  • test-workflows/loop-step.yaml test-workflows/test-module/loop-step.yaml
    Content is identical
  • test-workflows/ose.yaml test-workflows/test-module/ose.yaml
    Content is identical
  • ■ ■ ■ ■ ■ ■
    test-workflows/test-module/s3-cdn.yaml
     1 +name: s3-cdn
     2 + 
     3 +steps:
     4 + - scripts:
     5 + - "ExecCmd('mkdir -p /tmp/ott/')"
     6 + - "ExecCmd('seq 10 > /tmp/ott/source.txt')"
     7 + - "UploadToS3('/tmp/ott/on-s3.txt')"
     8 + - "DownloadFromS3('/tmp/ott/on-s3.txt', '/tmp/on-local-s3.txt')"
     9 + 
  • test-workflows/with-threadshold.yaml test-workflows/test-module/with-threadshold.yaml
    Content is identical
  • ■ ■ ■ ■ ■
    utils/helper.go
    skipped 7 lines
    8 8   "crypto/sha1"
    9 9   "encoding/base64"
    10 10   "fmt"
    11  - "github.com/flosch/pongo2/v6"
    12 11   "io"
    13 12   "io/ioutil"
    14 13   "math/rand"
    skipped 92 lines
    107 106  }
    108 107   
    109 108  // GetOSEnv get environment variable
    110  -func GetOSEnv(name string, alt string) string {
     109 +func GetOSEnv(name string, defaultValue string) string {
    111 110   variable, ok := os.LookupEnv(name)
    112 111   if !ok {
    113  - if alt != "" {
    114  - return alt
     112 + if defaultValue != "" {
     113 + return defaultValue
    115 114   }
    116 115   return name
    117 116   }
    skipped 764 lines
    882 881   return
    883 882  }
    884 883   
    885  -// OldRenderText resolve template from signature file
    886  -func OldRenderText(format string, data map[string]string) string {
     884 +// RenderText resolve template from signature file
     885 +func RenderText(format string, data map[string]string) string {
    887 886   t := template.Must(template.New("").Parse(format))
    888 887   buf := &bytes.Buffer{}
    889 888   err := t.Execute(buf, data)
    skipped 3 lines
    893 892   return buf.String()
    894 893  }
    895 894   
    896  -// RenderText resolve template from signature file
    897  -func RenderText(format string, data map[string]string) string {
    898  - // for backward compatibility because new template using `{{variable}}` instead of `{{.variable}}`
    899  - if strings.Contains(format, "{{.") {
    900  - return OldRenderText(format, data)
    901  - }
    902  - 
    903  - variable := make(map[string]interface{})
    904  - for k, v := range data {
    905  - variable[k] = v
    906  - }
    907  - if tpl, err := pongo2.FromString(format); err == nil {
    908  - out, ok := tpl.Execute(variable)
    909  - if ok == nil {
    910  - return out
    911  - }
    912  - ErrorF("Error when resolve template: %v", ok)
    913  - }
    914  - return format
    915  -}
    916  - 
  • ■ ■ ■ ■ ■ ■
    utils/log.go
    skipped 1 lines
    2 2   
    3 3  import (
    4 4   "fmt"
     5 + "io"
     6 + "io/ioutil"
     7 + "os"
     8 + "path/filepath"
     9 + "strings"
     10 + 
    5 11   "github.com/fatih/color"
    6 12   "github.com/j3ssie/osmedeus/libs"
    7 13   "github.com/kyokomi/emoji"
    8 14   "github.com/sirupsen/logrus"
    9 15   prefixed "github.com/x-cray/logrus-prefixed-formatter"
    10  - "io"
    11  - "io/ioutil"
    12  - "os"
    13  - "path/filepath"
    14  - "strings"
    15 16  )
    16 17   
    17 18  var logger = logrus.New()
    skipped 4 lines
    22 23   logDir := libs.LDIR
    23 24   if options.LogFile == "" {
    24 25   if !FolderExists(logDir) {
    25  - os.MkdirAll(logDir, 0766)
     26 + os.MkdirAll(logDir, 0777)
    26 27   }
    27 28   tmpFile, err := ioutil.TempFile(logDir, "osmedeus-*.log")
    28 29   if err == nil {
     30 + options.LogFile = tmpFile.Name()
     31 + } else {
     32 + tmpFile, _ := ioutil.TempFile("/tmp/", "osmedeus-*.log")
    29 33   options.LogFile = tmpFile.Name()
    30 34   }
    31 35   }
    32 36   
    33 37   logDir = filepath.Dir(options.LogFile)
    34 38   if !FolderExists(logDir) {
    35  - os.MkdirAll(logDir, 0755)
     39 + os.MkdirAll(logDir, 0777)
    36 40   }
    37 41   
    38 42   f, err := os.OpenFile(options.LogFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    39 43   if err != nil {
    40  - fmt.Fprintf(os.Stderr, "error opening log file: %v\n", logDir)
     44 + fmt.Fprintf(os.Stderr, "error opening log file: %v\n", options.LogFile)
    41 45   fmt.Fprintf(os.Stderr, "💡 You might want to switch to %v first via %v command", color.HiMagentaString("root user"), color.HiCyanString("sudo su"))
    42  - os.Exit(-1)
    43 46   } else {
    44 47   mwr = io.MultiWriter(os.Stdout, f)
    45 48   }
    skipped 82 lines
Please wait...
Page is in error, reload to recover