From 2b6c7a59631d82d1b0ca0d3f6b2ce89a888f2a7e Mon Sep 17 00:00:00 2001 From: Akilan Date: Fri, 15 Dec 2023 02:08:11 +0000 Subject: [PATCH] added support to generate Public and Private keys --- .gitignore | 7 + Bindings/Client.go | 3 +- config/config.go | 2 + config/generate/generate.go | 220 ++++++++++++----------- config/generate/generateFiles.go | 285 +++++++++++++++++------------- config/generate/gernerate_test.go | 43 +++-- go.mod | 1 + go.sum | 21 +++ 8 files changed, 331 insertions(+), 251 deletions(-) diff --git a/.gitignore b/.gitignore index f436bcc..1f8f00a 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,10 @@ server/docker/containers/ # generic folder to ignore export/ + +# Any testing file +test* + +# Ignore public and private keys +p2prc.publicKey +p2prc.privateKey diff --git a/Bindings/Client.go b/Bindings/Client.go index f584882..692fec7 100644 --- a/Bindings/Client.go +++ b/Bindings/Client.go @@ -3,6 +3,8 @@ package main import "C" import ( "encoding/json" + "time" + "github.com/Akilan1999/p2p-rendering-computation/abstractions" "github.com/Akilan1999/p2p-rendering-computation/client" "github.com/Akilan1999/p2p-rendering-computation/client/clientIPTable" @@ -10,7 +12,6 @@ import ( "github.com/Akilan1999/p2p-rendering-computation/p2p/frp" "github.com/Akilan1999/p2p-rendering-computation/plugin" "github.com/Akilan1999/p2p-rendering-computation/server" - "time" ) // The Client package where data-types diff --git a/config/config.go b/config/config.go index 374d963..1ccc772 100644 --- a/config/config.go +++ b/config/config.go @@ -31,6 +31,8 @@ type Config struct { FRPServerPort string BehindNAT string IPTableKey string + PublicKeyFile string + PrivateKeyFile string CustomConfig interface{} //NetworkInterface string //NetworkInterfaceIPV6Index int diff --git a/config/generate/generate.go b/config/generate/generate.go index 571618f..d8ed3ab 100644 --- a/config/generate/generate.go +++ b/config/generate/generate.go @@ -1,22 +1,22 @@ package generate import ( - "github.com/Akilan1999/p2p-rendering-computation/config" - "math/rand" - "os" - "time" + "github.com/Akilan1999/p2p-rendering-computation/config" + "math/rand" + "os" + "time" ) var ( - defaults = map[string]interface{}{} - configPaths []string - defaultEnvName = "P2PRC" + defaults = map[string]interface{}{} + configPaths []string + defaultEnvName = "P2PRC" ) // GetPathP2PRC Getting P2PRC Directory from environment variable func GetPathP2PRC() (string, error) { - curDir := os.Getenv(defaultEnvName) - return curDir + "/", nil + curDir := os.Getenv(defaultEnvName) + return curDir + "/", nil } // SetEnvName Sets the environment name @@ -24,132 +24,142 @@ func GetPathP2PRC() (string, error) { // your environment variable // This is useful when extending the use case of P2PRC func SetEnvName(EnvName string) error { - if EnvName != "" { - defaultEnvName = EnvName - } - // Handling error to be implemented only if needed - return nil + if EnvName != "" { + defaultEnvName = EnvName + } + // Handling error to be implemented only if needed + return nil } // GetCurrentPath Getting P2PRC Directory from environment variable func GetCurrentPath() (string, error) { - curDir := os.Getenv("PWD") - return curDir + "/", nil + curDir := os.Getenv("PWD") + return curDir + "/", nil } // SetDefaults This function to be called only during a // make install func SetDefaults(envName string, forceDefault bool, CustomConfig interface{}, NoBoilerPlate bool, ConfigUpdate ...*config.Config) (*config.Config, error) { - //Setting current directory to default path - defaultPath, err := GetCurrentPath() - if err != nil { - return nil, err - } + //Setting current directory to default path + defaultPath, err := GetCurrentPath() + if err != nil { + return nil, err + } - // Set Env name - err = config.SetEnvName(envName) - if err != nil { - return nil, err - } + // Set Env name + err = config.SetEnvName(envName) + if err != nil { + return nil, err + } - ////Creates ip_table.json in the json directory - //err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json") - //if err != nil { - // return err - //} - // - ////Creates a copy of trackcontainers.json in the appropriate directory - //err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json") - //if err != nil { - // return err - //} - // - ////Creates a copy of trackcontainers.json in the appropriate directory - //err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json") - //if err != nil { - // return err - //} + ////Creates ip_table.json in the json directory + //err = Copy("p2p/ip_table.json", "p2p/iptable/ip_table.json") + //if err != nil { + // return err + //} + // + ////Creates a copy of trackcontainers.json in the appropriate directory + //err = Copy("client/trackcontainers.json", "client/trackcontainers/trackcontainers.json") + //if err != nil { + // return err + //} + // + ////Creates a copy of trackcontainers.json in the appropriate directory + //err = Copy("client/grouptrackcontainers.json", "client/trackcontainers/grouptrackcontainers.json") + //if err != nil { + // return err + //} - var Defaults config.Config + var Defaults config.Config - if len(ConfigUpdate) == 0 { - //Setting default paths for the config file - Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json" - Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/" - Defaults.DockerContainers = defaultPath + "server/docker/containers/" - Defaults.SpeedTestFile = defaultPath + "p2p/50.bin" - Defaults.IPV6Address = "" - Defaults.PluginPath = defaultPath + "plugin/deploy" - Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json" - Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json" - Defaults.ServerPort = "8088" - Defaults.FRPServerPort = "True" - Defaults.CustomConfig = CustomConfig - Defaults.BehindNAT = "True" - Defaults.DockerRunLogs = "/tmp/" - // Generate a random key to be added to IPTable - Defaults.IPTableKey = String(12) - // Random name generator - hostname, err := os.Hostname() - if err != nil { - return nil, err - } + if len(ConfigUpdate) == 0 { + //Setting default paths for the config file + Defaults.IPTable = defaultPath + "p2p/iptable/ip_table.json" + Defaults.DefaultDockerFile = defaultPath + "server/docker/containers/docker-ubuntu-sshd/" + Defaults.DockerContainers = defaultPath + "server/docker/containers/" + Defaults.SpeedTestFile = defaultPath + "p2p/50.bin" + Defaults.IPV6Address = "" + Defaults.PluginPath = defaultPath + "plugin/deploy" + Defaults.TrackContainersPath = defaultPath + "client/trackcontainers/trackcontainers.json" + Defaults.GroupTrackContainersPath = defaultPath + "client/trackcontainers/grouptrackcontainers.json" + Defaults.ServerPort = "8088" + Defaults.FRPServerPort = "True" + Defaults.CustomConfig = CustomConfig + Defaults.BehindNAT = "True" + Defaults.DockerRunLogs = "/tmp/" + // Generate a random key to be added to IPTable + Defaults.IPTableKey = String(12) + // Random name generator + hostname, err := os.Hostname() + if err != nil { + return nil, err + } - Defaults.MachineName = hostname + "-" + String(7) - } else { - Defaults = *ConfigUpdate[0] - } + // Generate Public and private keys and set path + Defaults.PublicKeyFile = defaultPath + "p2prc.publicKey" + Defaults.PrivateKeyFile = defaultPath + "p2prc.privateKey" - //defaults["NetworkInterface"] = "wlp0s20f3" - //defaults["NetworkInterfaceIPV6Index"] = "2" + // Generate SSH keys + err = MakeSSHKeyPair(Defaults.PublicKeyFile, Defaults.PrivateKeyFile) + if err != nil { + return nil, err + } - //Paths to search for config file - configPaths = append(configPaths, defaultPath) + Defaults.MachineName = hostname + "-" + String(7) + } else { + Defaults = *ConfigUpdate[0] + } - if fileExists(defaultPath+"config.json") && forceDefault { - err := os.Remove(defaultPath + "config.json") - if err != nil { - return nil, err - } - } + //defaults["NetworkInterface"] = "wlp0s20f3" + //defaults["NetworkInterfaceIPV6Index"] = "2" - // write defaults to the config file - err = Defaults.WriteConfig() - if err != nil { - return nil, err - } + //Paths to search for config file + configPaths = append(configPaths, defaultPath) - //Calling configuration file - Config, err := config.ConfigInit(defaults, nil, envName) - if err != nil { - return nil, err - } + if fileExists(defaultPath+"config.json") && forceDefault { + err := os.Remove(defaultPath + "config.json") + if err != nil { + return nil, err + } + } - if !NoBoilerPlate { - err = GenerateFiles() - if err != nil { - return nil, err - } - } + // write defaults to the config file + err = Defaults.WriteConfig() + if err != nil { + return nil, err + } - return Config, nil + //Calling configuration file + Config, err := config.ConfigInit(defaults, nil, envName) + if err != nil { + return nil, err + } + + if !NoBoilerPlate { + err = GenerateFiles() + if err != nil { + return nil, err + } + } + + return Config, nil } // Generating a random string const charset = "abcdefghijklmnopqrstuvwxyz" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" var seededRand *rand.Rand = rand.New( - rand.NewSource(time.Now().UnixNano())) + rand.NewSource(time.Now().UnixNano())) func StringWithCharset(length int, charset string) string { - b := make([]byte, length) - for i := range b { - b[i] = charset[seededRand.Intn(len(charset))] - } - return string(b) + b := make([]byte, length) + for i := range b { + b[i] = charset[seededRand.Intn(len(charset))] + } + return string(b) } func String(length int) string { - return StringWithCharset(length, charset) + return StringWithCharset(length, charset) } diff --git a/config/generate/generateFiles.go b/config/generate/generateFiles.go index 4d3ce7b..1b5585a 100644 --- a/config/generate/generateFiles.go +++ b/config/generate/generateFiles.go @@ -1,163 +1,196 @@ package generate import ( - "github.com/Akilan1999/p2p-rendering-computation/p2p" - "github.com/go-git/go-git/v5" - "os" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "github.com/Akilan1999/p2p-rendering-computation/p2p" + "github.com/go-git/go-git/v5" + "golang.org/x/crypto/ssh" + "io/ioutil" + "os" ) // GenerateFiles Generates all the files needed to setup P2PRC func GenerateFiles(rootNodes ...p2p.IpAddress) (err error) { - err = GenerateIPTableFile(rootNodes) - err = GenerateDockerFiles() - err = GeneratePluginDirectory() - err = GenerateClientTrackContainers() - return + err = GenerateIPTableFile(rootNodes) + err = GenerateDockerFiles() + err = GeneratePluginDirectory() + err = GenerateClientTrackContainers() + return } // GenerateIPTableFile Generates the IPTable file with the appropirate root node func GenerateIPTableFile(rootNodes []p2p.IpAddress) (err error) { - var rootnodes p2p.IpAddresses - var rootnode p2p.IpAddress + var rootnodes p2p.IpAddresses + var rootnode p2p.IpAddress - err = CreateIPTableFolderStructure() - if err != nil { - return err - } + err = CreateIPTableFolderStructure() + if err != nil { + return err + } - // If root node addresses are not provided as optional parameters - if len(rootNodes) <= 0 { - rootnode.Name = "Node1" - rootnode.ServerPort = "8078" - rootnode.NAT = "False" - rootnode.Ipv4 = "139.59.162.154" + // If root node addresses are not provided as optional parameters + if len(rootNodes) <= 0 { + rootnode.Name = "Node1" + rootnode.ServerPort = "8078" + rootnode.NAT = "False" + rootnode.Ipv4 = "139.59.162.154" - rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode) - } else { - // if root nodes are provided then override them as the optional parameter - for i := range rootNodes { - rootnodes.IpAddress = append(rootnodes.IpAddress, rootNodes[i]) - } - } + rootnodes.IpAddress = append(rootnodes.IpAddress, rootnode) + } else { + // if root nodes are provided then override them as the optional parameter + for i := range rootNodes { + rootnodes.IpAddress = append(rootnodes.IpAddress, rootNodes[i]) + } + } - err = rootnodes.WriteIpTable() - return + err = rootnodes.WriteIpTable() + return } // CreateIPTableFolderStructure Create folder structure for IPTable func CreateIPTableFolderStructure() (err error) { - path, err := GetCurrentPath() - if err != nil { - return err - } - if _, err = os.Stat(path + "p2p"); os.IsNotExist(err) { - if err = os.Mkdir(path+"p2p", os.ModePerm); err != nil { - return err - } - } - if _, err = os.Stat(path + "p2p/iptable"); os.IsNotExist(err) { - if err = os.Mkdir(path+"p2p/iptable", os.ModePerm); err != nil { - return err - } - } - if _, err = os.Stat(path + "p2p/iptable/ip_table.json"); os.IsNotExist(err) { - _, err = os.Create(path + "p2p/iptable/ip_table.json") - if err != nil { - return err - } - } + path, err := GetCurrentPath() + if err != nil { + return err + } + if _, err = os.Stat(path + "p2p"); os.IsNotExist(err) { + if err = os.Mkdir(path+"p2p", os.ModePerm); err != nil { + return err + } + } + if _, err = os.Stat(path + "p2p/iptable"); os.IsNotExist(err) { + if err = os.Mkdir(path+"p2p/iptable", os.ModePerm); err != nil { + return err + } + } + if _, err = os.Stat(path + "p2p/iptable/ip_table.json"); os.IsNotExist(err) { + _, err = os.Create(path + "p2p/iptable/ip_table.json") + if err != nil { + return err + } + } - return + return } // GenerateDockerFiles Generate default docker files func GenerateDockerFiles() (err error) { - path, err := GetCurrentPath() - if err != nil { - return err - } - if _, err = os.Stat(path + "server"); os.IsNotExist(err) { - if err = os.Mkdir(path+"server", os.ModePerm); err != nil { - return err - } - if _, err = os.Stat(path + "server/docker"); os.IsNotExist(err) { - if err = os.Mkdir(path+"server/docker", os.ModePerm); err != nil { - return err - } - } - if _, err = os.Stat(path + "server/docker/containers"); os.IsNotExist(err) { - if err = os.Mkdir(path+"server/docker/containers", os.ModePerm); err != nil { - return err - } - } - if _, err = os.Stat(path + "server/docker/containers"); os.IsNotExist(err) { - if err = os.Mkdir(path+"server/docker/containers", os.ModePerm); err != nil { - return err - } - } - if _, err = os.Stat(path + "server/docker/containers/docker-ubuntu-sshd"); os.IsNotExist(err) { - if err = os.Mkdir(path+"server/docker/containers/docker-ubuntu-sshd", os.ModePerm); err != nil { - return err - } - } + path, err := GetCurrentPath() + if err != nil { + return err + } + if _, err = os.Stat(path + "server"); os.IsNotExist(err) { + if err = os.Mkdir(path+"server", os.ModePerm); err != nil { + return err + } + if _, err = os.Stat(path + "server/docker"); os.IsNotExist(err) { + if err = os.Mkdir(path+"server/docker", os.ModePerm); err != nil { + return err + } + } + if _, err = os.Stat(path + "server/docker/containers"); os.IsNotExist(err) { + if err = os.Mkdir(path+"server/docker/containers", os.ModePerm); err != nil { + return err + } + } + if _, err = os.Stat(path + "server/docker/containers"); os.IsNotExist(err) { + if err = os.Mkdir(path+"server/docker/containers", os.ModePerm); err != nil { + return err + } + } + if _, err = os.Stat(path + "server/docker/containers/docker-ubuntu-sshd"); os.IsNotExist(err) { + if err = os.Mkdir(path+"server/docker/containers/docker-ubuntu-sshd", os.ModePerm); err != nil { + return err + } + } - } + } - // Clone base docker image - _, err = git.PlainClone(path+"server/docker/containers/docker-ubuntu-sshd", false, &git.CloneOptions{ - URL: "https://github.com/Akilan1999/docker-ubuntu-sshd", - Progress: os.Stdout, - }) - if err != nil { - return err - } + // Clone base docker image + _, err = git.PlainClone(path+"server/docker/containers/docker-ubuntu-sshd", false, &git.CloneOptions{ + URL: "https://github.com/Akilan1999/docker-ubuntu-sshd", + Progress: os.Stdout, + }) + if err != nil { + return err + } - return + return } // GeneratePluginDirectory Generates plugin directory structure func GeneratePluginDirectory() (err error) { - path, err := GetCurrentPath() - if err != nil { - return err - } - if _, err = os.Stat(path + "plugin"); os.IsNotExist(err) { - if err = os.Mkdir(path+"plugin", os.ModePerm); err != nil { - return err - } - if _, err = os.Stat(path + "plugin/deploy"); os.IsNotExist(err) { - if err = os.Mkdir(path+"plugin/deploy", os.ModePerm); err != nil { - return err - } - } - } - return + path, err := GetCurrentPath() + if err != nil { + return err + } + if _, err = os.Stat(path + "plugin"); os.IsNotExist(err) { + if err = os.Mkdir(path+"plugin", os.ModePerm); err != nil { + return err + } + if _, err = os.Stat(path + "plugin/deploy"); os.IsNotExist(err) { + if err = os.Mkdir(path+"plugin/deploy", os.ModePerm); err != nil { + return err + } + } + } + return } func GenerateClientTrackContainers() (err error) { - path, err := GetCurrentPath() - if err != nil { - return err - } - if _, err = os.Stat(path + "client"); os.IsNotExist(err) { - if err = os.Mkdir(path+"client", os.ModePerm); err != nil { - return err - } - if err = os.Mkdir(path+"client/trackcontainers", os.ModePerm); err != nil { - return err - } + path, err := GetCurrentPath() + if err != nil { + return err + } + if _, err = os.Stat(path + "client"); os.IsNotExist(err) { + if err = os.Mkdir(path+"client", os.ModePerm); err != nil { + return err + } + if err = os.Mkdir(path+"client/trackcontainers", os.ModePerm); err != nil { + return err + } - if _, err = os.Stat(path + "client/trackcontainers/trackcontainers.json"); os.IsNotExist(err) { - _, err = os.Create(path + "client/trackcontainers/trackcontainers.json") - if err != nil { - return err - } - _, err = os.Create(path + "client/trackcontainers/grouptrackcontainers.json") - if err != nil { - return err - } - } + if _, err = os.Stat(path + "client/trackcontainers/trackcontainers.json"); os.IsNotExist(err) { + _, err = os.Create(path + "client/trackcontainers/trackcontainers.json") + if err != nil { + return err + } + _, err = os.Create(path + "client/trackcontainers/grouptrackcontainers.json") + if err != nil { + return err + } + } - } - return + } + return +} + +// MakeSSHKeyPair make a pair of public and private keys for SSH access. +// Public key is encoded in the format for inclusion in an OpenSSH authorized_keys file. +// Private Key generated is PEM encoded +// source: https://gist.github.com/goliatone/e9c13e5f046e34cef6e150d06f20a34c +func MakeSSHKeyPair(pubKeyPath, privateKeyPath string) error { + privateKey, err := rsa.GenerateKey(rand.Reader, 1024) + if err != nil { + return err + } + // generate and write private key as PEM + privateKeyFile, err := os.Create(privateKeyPath) + defer privateKeyFile.Close() + if err != nil { + return err + } + privateKeyPEM := &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(privateKey)} + if err := pem.Encode(privateKeyFile, privateKeyPEM); err != nil { + return err + } + // generate and write public key + pub, err := ssh.NewPublicKey(&privateKey.PublicKey) + if err != nil { + return err + } + return ioutil.WriteFile(pubKeyPath, ssh.MarshalAuthorizedKey(pub), 0655) } diff --git a/config/generate/gernerate_test.go b/config/generate/gernerate_test.go index 6437795..b48edf2 100644 --- a/config/generate/gernerate_test.go +++ b/config/generate/gernerate_test.go @@ -1,35 +1,40 @@ package generate import ( - "fmt" - "github.com/Akilan1999/p2p-rendering-computation/config" - "testing" + "fmt" + "github.com/Akilan1999/p2p-rendering-computation/config" + "testing" ) type CustomConfig struct { - Test string + Test string } // Test case to generate defaults with custom data-structure func TestSetDefaults(t *testing.T) { - setDefaults, err := SetDefaults("", true, &CustomConfig{Test: "lol"}, true) - if err != nil { - fmt.Println(err) - t.Fail() - return - } + setDefaults, err := SetDefaults("", true, &CustomConfig{Test: "lol"}, true) + if err != nil { + fmt.Println(err) + t.Fail() + return + } - fmt.Println(setDefaults) + fmt.Println(setDefaults) - var c CustomConfig + var c CustomConfig - _, err = config.ConfigInit(nil, &c) - if err != nil { - fmt.Println(err) - t.Fail() - return - } + _, err = config.ConfigInit(nil, &c) + if err != nil { + fmt.Println(err) + t.Fail() + return + } - fmt.Println(c) + fmt.Println(c) } + +// Test case to generate public and private keys +func TestGeneratePublicAndPrivateKeys(t *testing.T) { + MakeSSHKeyPair("test.pub", "test.prv") +} diff --git a/go.mod b/go.mod index eefaf53..16f4361 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/urfave/cli/v2 v2.3.0 gitlab.com/NebulousLabs/fastrand v0.0.0-20181126182046-603482d69e40 // indirect gitlab.com/NebulousLabs/go-upnp v0.0.0-20181011194642-3a71999ed0d3 + golang.org/x/crypto v0.16.0 // indirect gopkg.in/yaml.v2 v2.4.0 gotest.tools/v3 v3.0.3 // indirect ) diff --git a/go.sum b/go.sum index 89a3c7f..3ba177b 100644 --- a/go.sum +++ b/go.sum @@ -891,6 +891,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -928,6 +930,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -988,6 +991,9 @@ golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1020,6 +1026,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1117,9 +1125,17 @@ golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1130,6 +1146,10 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1200,6 +1220,7 @@ golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=