From 22c8fefd8d6f5e1d0e45cf48073388e29f40b2f7 Mon Sep 17 00:00:00 2001 From: Akilan Date: Wed, 13 Nov 2024 17:55:43 +0000 Subject: [PATCH] added base mechanism to add public keys from the propogated from the IPTable --- p2p/speedtest.go | 29 ++++++++++ p2p/ssh_autorisation.go | 123 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 p2p/ssh_autorisation.go diff --git a/p2p/speedtest.go b/p2p/speedtest.go index 4957181..0468b07 100644 --- a/p2p/speedtest.go +++ b/p2p/speedtest.go @@ -1,5 +1,9 @@ package p2p +import ( + "github.com/Akilan1999/p2p-rendering-computation/config" +) + // SpeedTest Runs a speed test and does updates IP tables accordingly func (ip *IpAddresses) SpeedTest() error { @@ -50,11 +54,26 @@ func (ip *IpAddresses) SpeedTest() error { // SpeedTestUpdatedIPTable Called when ip tables from httpclient/server is also passed on func (ip *IpAddresses) SpeedTestUpdatedIPTable() error { + + Config, err := config.ConfigInit(nil, nil) + if err != nil { + return err + } + targets, err := ReadIpTable() if err != nil { return err } + // Checks if baremetal mode and unsafe mode + // is enabled. If it is enabled it adds the + // the propagated public key to the list. + + AddPublicKey := false + if Config.BareMetal && Config.UnsafeMode { + AddPublicKey = true + } + // To ensure struct has no duplicates IP addresses //DoNotRead := targets @@ -64,6 +83,16 @@ func (ip *IpAddresses) SpeedTestUpdatedIPTable() error { //To ensure that there are no duplicate IP addresses Exists := false for k := range ip.IpAddress { + if AddPublicKey && ip.IpAddress[k].PublicKey != "" { + // This function call (AddAuthorisationKey) is inefficient but to be optimised later on. + // This is because when if the user is running on as unsafe mode the authorization file + // is opened from the SSH directory and then iterates through every single SSH entry + // to find out if the SSH entry exists or not. This will incur multiple CPU cycles + // for no reason. A better approach would be to have been to store the states on memory and only + // add when needed based on the memory location. This is something is to be discussed + // and look upon later on. + AddAuthorisationKey(ip.IpAddress[k].PublicKey) + } // Checks if both the IPV4 addresses are the same or the IPV6 address is not // an empty string and IPV6 address are the same if (ip.IpAddress[k].Ipv4 == targets.IpAddress[i].Ipv4 && targets.IpAddress[i].NAT == "True") || (targets.IpAddress[i].Ipv6 != "" && ip.IpAddress[k].Ipv6 == targets.IpAddress[i].Ipv6) { diff --git a/p2p/ssh_autorisation.go b/p2p/ssh_autorisation.go new file mode 100644 index 0000000..89b4a86 --- /dev/null +++ b/p2p/ssh_autorisation.go @@ -0,0 +1,123 @@ +// NOTE: Most of the code snippet was generated using ChatGPT +// Prompt used: "generate go program to read and populate ssh authorization file" + +package p2p + +import ( + "bufio" + "errors" + "fmt" + "os" + "path/filepath" + "strings" +) + +// GetAuthorizedKeysPath returns the path to the authorized_keys file +func GetAuthorizedKeysPath() (string, error) { + homeDir, err := os.UserHomeDir() + if err != nil { + return "", fmt.Errorf("could not find home directory: %v", err) + } + return filepath.Join(homeDir, ".ssh", "authorized_keys"), nil +} + +// ReadAuthorizedKeys reads and returns the current contents of the authorized_keys file as a map +func ReadAuthorizedKeys(path string) (map[string]bool, error) { + file, err := os.Open(path) + if err != nil { + return nil, fmt.Errorf("could not open authorized_keys file: %v", err) + } + defer file.Close() + + keys := make(map[string]bool) + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + // Skip empty lines and comments + if line != "" && !strings.HasPrefix(line, "#") { + keys[line] = true + } + } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error reading authorized_keys file: %v", err) + } + return keys, nil +} + +// AddKeyToAuthorizedKeys adds a new key to the authorized_keys file if it doesn’t already exist +func AddKeyToAuthorizedKeys(path, newKey string) error { + keys, err := ReadAuthorizedKeys(path) + if err != nil { + return err + } + + // Check if the key already exists in the map + if keys[newKey] { + return errors.New("key already exists in authorized_keys") + } + + // Append the new key + file, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return fmt.Errorf("could not open authorized_keys file for writing: %v", err) + } + defer file.Close() + + if _, err := file.WriteString(newKey + "\n"); err != nil { + return fmt.Errorf("could not write to authorized_keys file: %v", err) + } + return nil +} + +func RemoveKeyFromAuthorizedKeys(path, keyToRemove string) error { + keys, err := ReadAuthorizedKeys(path) + if err != nil { + return err + } + + // Check if the key exists in the map + if !keys[keyToRemove] { + return errors.New("key not found in authorized_keys") + } + + // Delete the key from the map + delete(keys, keyToRemove) + + // Write updated keys back to the authorized_keys file + file, err := os.OpenFile(path, os.O_TRUNC|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return fmt.Errorf("could not open authorized_keys file for writing: %v", err) + } + defer file.Close() + + for key := range keys { + if _, err := file.WriteString(key + "\n"); err != nil { + return fmt.Errorf("could not write to authorized_keys file: %v", err) + } + } + + return nil +} + +// AddAuthorisationKey Adds public key provided to the +// authorization file so that nodes can SSH into +// the +func AddAuthorisationKey(PublicKey string) error { + path, err := GetAuthorizedKeysPath() + if err != nil { + return err + } + + // Display existing keys + _, err = ReadAuthorizedKeys(path) + if err != nil { + return err + } + + err = AddKeyToAuthorizedKeys(path, PublicKey) + if err != nil { + return err + } + + return nil +}