server.garden privileged automation agent
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

131 lines
3.3 KiB

package main
import (
"fmt"
"os"
"os/exec"
"os/user"
"regexp"
"strings"
"time"
errors "git.sequentialread.com/forest/pkg-errors"
"git.sequentialread.com/forest/rootsystem/configuration"
"git.sequentialread.com/forest/rootsystem/objectStorage"
)
func main() {
config, _, err := configuration.LoadConfiguration()
if err != nil {
panic(errors.Wrap(err, "host-key-poller failed because loadConfiguration() returned"))
}
storage, err := objectStorage.InitializeObjectStorage(config, false)
if err != nil {
panic(errors.Wrap(err, "host-key-poller failed to initialize object storage"))
}
iterations := 0
for iterations < 200 { // waits for a maximum of 200*5 seconds = 1000 seconds
iterations++
filename := fmt.Sprintf("rootsystem/known-hosts/%s", os.Args[1])
fmt.Printf("polling for %s...\n", filename)
file, notFound, err := storage.Get(filename)
if err != nil && !notFound {
fmt.Printf("the error was: %s\n", err)
}
if err == nil && !notFound {
lines := strings.Split(string(file.Content), "\n")
validLines := []string{}
ipAddress := ""
for _, line := range lines {
if len(strings.Trim(line, "\t \n\r")) > 10 {
fields := strings.Split(line, " ")
if len(fields) >= 3 {
ip := fields[0]
hostKeyType := fields[1]
base64PublicKey := fields[2]
ipValid := regexp.MustCompile("(\\d+\\.)+\\d+").FindString(ip) != ""
typeValid := (hostKeyType == "ecdsa-sha2-nistp256" || hostKeyType == "ssh-rsa" || hostKeyType == "ssh-ed25519")
base64Valid := regexp.MustCompile("[A-Za-z0-9+/=]+").FindString(base64PublicKey) != ""
if ipValid && typeValid && base64Valid {
ipAddress = ip
validLines = append(validLines, fmt.Sprintf("%s %s %s", ip, hostKeyType, base64PublicKey))
}
}
}
}
if len(validLines) > 0 {
sshFolder := getCurrentUserSSHFolder()
_, err := os.Stat(sshFolder)
if err != nil {
err := os.Mkdir(sshFolder, 0700)
if err != nil {
panic(err)
}
}
knownHostsFilename := getKnownHostsFilename()
_, err = os.Stat(knownHostsFilename)
if err == nil {
fmt.Printf("Removing %s from %s:\n", ipAddress, knownHostsFilename)
fmt.Printf("ssh-keygen -f %s -R %s\n", knownHostsFilename, ipAddress)
process := exec.Command("ssh-keygen", "-f", knownHostsFilename, "-R", ipAddress)
err := process.Start()
if err != nil {
panic(err)
}
err = process.Wait()
if err != nil {
panic(err)
}
} else {
fmt.Printf("%s doesn't exist yet, creating it...\n", knownHostsFilename)
}
file, err := os.OpenFile(knownHostsFilename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
panic(err)
}
defer file.Close()
fmt.Printf("Writing to %s:\n", knownHostsFilename)
for _, line := range validLines {
fmt.Println(line)
if _, err = file.WriteString(fmt.Sprintf("\n%s", line)); err != nil {
panic(err)
}
}
os.Exit(0)
}
}
time.Sleep(time.Second * time.Duration(5))
}
panic(errors.New("Timed Out"))
}
func getCurrentUserSSHFolder() string {
user, err := user.Current()
if err != nil {
panic(errors.Wrap(err, "getKnownHostsFilename(): "))
}
return fmt.Sprintf("%s/.ssh", user.HomeDir)
}
func getKnownHostsFilename() string {
return fmt.Sprintf("%s/known_hosts", getCurrentUserSSHFolder())
}