package generate import ( "crypto/rand" "crypto/rsa" "crypto/x509" "encoding/pem" "github.com/Akilan1999/p2p-rendering-computation/config" "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) if err != nil { return err } err = GenerateDockerFiles() if err != nil { return err } err = GeneratePluginDirectory() if err != nil { return err } 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 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 = "217.76.63.222" rootnode.ProxyServer = "True" 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 } // CreateIPTableFolderStructure Create folder structure for IPTable func CreateIPTableFolderStructure() (err error) { path, err := config.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 } // GenerateDockerFiles Generate default docker files func GenerateDockerFiles() (err error) { path, err := config.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 } return } // GeneratePluginDirectory Generates plugin directory structure func GeneratePluginDirectory() (err error) { path, err := config.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 := config.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 } } } 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 } // Set permission to private key to SSH into docker machine err = os.Chmod(privateKeyPath, 600) 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) } // FileExists exists returns whether the given file or directory exists // source: https://stackoverflow.com/questions/10510691/how-to-check-whether-a-file-or-directory-exists func FileExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } // AuthorizedKey struct represents the structure of an authorized key type AuthorizedKey struct { Username string Key string } // AddPublicKeyBareMetal Adds the parameter public key to the auth list // Generated by ChatGPT // Prompts: // - Generate a go program to read authorised key and map it to a struct and write it back to the same location. // - Can you follow the original format // (TURNED OUT TO BE PRETTY SHITTY GENERATED CODE) //func AddPublicKeyBareMetal(PublicKey string) error { // // Specify the path to the authorized_keys file // dirname, err := os.UserHomeDir() // if err != nil { // return err // } // // authorizedKeysPath := dirname + "/.ssh/" + "authorized_keys" // // // Read the contents of the authorized_keys file // file, err := os.Open(authorizedKeysPath) // if err != nil { // return err // } // defer file.Close() // // // Create a slice to store AuthorizedKey structs // var authorizedKeys []AuthorizedKey // // // Read each line of the file and parse the data // scanner := bufio.NewScanner(file) // for scanner.Scan() { // line := scanner.Text() // parts := strings.Fields(line) // if len(parts) >= 2 { // authorizedKey := AuthorizedKey{ // Username: parts[0], // Key: parts[1], // } // authorizedKeys = append(authorizedKeys, authorizedKey) // } // } // // if err := scanner.Err(); err != nil { // return err // } // // // Modify the slice of structs if needed // // authorizedKeys[0].Username = "newUsername" // // authorizedKeys[0].Key = "newKey" // authorizedKeys = append(authorizedKeys, AuthorizedKey{Username: "", Key: PublicKey}) // // // Write the modified data back to the authorized_keys file // newFile, err := os.Create(authorizedKeysPath) // if err != nil { // return err // } // defer newFile.Close() // // return nil //}