starting ssh client

This commit is contained in:
Kristian 2023-08-21 04:10:25 +02:00
parent 314a403ed9
commit 488f733ab1
9 changed files with 258 additions and 12 deletions

View File

@ -1,3 +1,4 @@
export BOT_TOKEN= export BOT_TOKEN=
export CRYPTO_TOKEN= export CRYPTO_TOKEN=
export OPENAI_TOKEN= export OPENAI_TOKEN=
export ADMIN_DISCORD_ID=

2
.gitignore vendored
View File

@ -1,2 +1,4 @@
.env .env
pb_data pb_data
*.pem
*.pub

View File

@ -1,6 +1,7 @@
package bot package bot
import ( import (
"bitbot/pb"
"os" "os"
"os/signal" "os/signal"
"strings" "strings"
@ -11,9 +12,10 @@ import (
) )
var ( var (
BotToken string BotToken string
OpenAIToken string OpenAIToken string
CryptoToken string CryptoToken string
AllowedUserID string
) )
func Run() { func Run() {
@ -26,7 +28,7 @@ func Run() {
discord.Open() discord.Open()
defer discord.Close() defer discord.Close()
pb.Run()
log.Info("BitBot is running...") log.Info("BitBot is running...")
c := make(chan os.Signal, 1) c := make(chan os.Signal, 1)
@ -56,11 +58,63 @@ func newMessage(discord *discordgo.Session, message *discordgo.MessageCreate) {
conversationHistory = append(conversationHistory, userMessage) conversationHistory = append(conversationHistory, userMessage)
if strings.Contains(message.Content, "!bit") || isPrivateChannel { if strings.Contains(message.Content, "!cry") {
chatGPT(discord, message.ChannelID, message.Content, conversationHistory)
} else if strings.Contains(message.Content, "!cry") {
currentCryptoPrice := getCurrentCryptoPrice(message.Content) currentCryptoPrice := getCurrentCryptoPrice(message.Content)
discord.ChannelMessageSendComplex(message.ChannelID, currentCryptoPrice) discord.ChannelMessageSendComplex(message.ChannelID, currentCryptoPrice)
} else if strings.Contains(message.Content, "!bit") || isPrivateChannel {
chatGPT(discord, message.ChannelID, message.Content, conversationHistory)
} else if strings.Contains(message.Content, "!genkey") {
if message.Author.ID == AllowedUserID {
err := GenerateAndSaveSSHKeyPairIfNotExist()
if err != nil {
discord.ChannelMessageSend(message.ChannelID, "Error generating or saving key pair.")
return
}
discord.ChannelMessageSend(message.ChannelID, "SSH key pair generated and saved successfully!")
} else {
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
}
} else if strings.Contains(message.Content, "!showkey") {
if message.Author.ID == AllowedUserID {
publicKey, err := GetPublicKey()
if err != nil {
discord.ChannelMessageSend(message.ChannelID, "Error fetching public key.")
return
}
discord.ChannelMessageSend(message.ChannelID, publicKey)
} else {
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
}
} else if strings.Contains(message.Content, "!regenkey") {
if message.Author.ID == AllowedUserID {
err := GenerateAndSaveSSHKeyPair()
if err != nil {
discord.ChannelMessageSend(message.ChannelID, "Error regenerating and saving key pair.")
return
}
discord.ChannelMessageSend(message.ChannelID, "SSH key pair regenerated and saved successfully!")
} else {
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
}
} else if strings.Contains(message.Content, "!ssh") {
if message.Author.ID == AllowedUserID {
commandParts := strings.Fields(message.Content)
if len(commandParts) != 2 {
discord.ChannelMessageSend(message.ChannelID, "Invalid command format. Use !ssh username@remote-host:port")
return
}
connectionDetails := commandParts[1]
err := SSHConnectToRemoteServer(connectionDetails)
if err != nil {
discord.ChannelMessageSend(message.ChannelID, "Error connecting to remote server.")
return
}
discord.ChannelMessageSend(message.ChannelID, "Connected to remote server!")
} else {
discord.ChannelMessageSend(message.ChannelID, "You are not authorized to use this command.")
}
} }
conversationHistoryMap[userID] = conversationHistory conversationHistoryMap[userID] = conversationHistory

View File

@ -3,7 +3,7 @@ package bot
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io/ioutil" "io"
"net/http" "net/http"
"regexp" "regexp"
"strconv" "strconv"
@ -41,7 +41,7 @@ func getCurrentCryptoPrice(message string) *discordgo.MessageSend {
} }
} }
body, _ := ioutil.ReadAll(response.Body) body, _ := io.ReadAll(response.Body)
defer response.Body.Close() defer response.Body.Close()
var data CryptoData var data CryptoData

185
bot/sshclient.go Normal file
View File

@ -0,0 +1,185 @@
package bot
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
"errors"
"os"
"strings"
"golang.org/x/crypto/ssh"
)
const (
privateKeyPath = "private_key.pem"
publicKeyPath = "public_key.pub"
bits = 2048
)
func GenerateAndSaveSSHKeyPairIfNotExist() error {
if KeyFilesExist(privateKeyPath, publicKeyPath) {
return nil
}
privateKey, publicKey, err := GenerateSSHKeyPair(bits)
if err != nil {
return err
}
err = SavePrivateKeyToFile(privateKeyPath, privateKey)
if err != nil {
return err
}
err = SavePublicKeyToFile(publicKeyPath, publicKey)
if err != nil {
return err
}
return nil
}
func GenerateAndSaveSSHKeyPair() error {
privateKey, publicKey, err := GenerateSSHKeyPair(bits)
if err != nil {
return err
}
err = SavePrivateKeyToFile(privateKeyPath, privateKey)
if err != nil {
return err
}
err = SavePublicKeyToFile(publicKeyPath, publicKey)
if err != nil {
return err
}
return nil
}
func KeyFilesExist(privateKeyPath, publicKeyPath string) bool {
_, privateKeyErr := os.Stat(privateKeyPath)
_, publicKeyErr := os.Stat(publicKeyPath)
return !os.IsNotExist(privateKeyErr) && !os.IsNotExist(publicKeyErr)
}
func GenerateSSHKeyPair(bits int) (*rsa.PrivateKey, ssh.PublicKey, error) {
privateKey, err := rsa.GenerateKey(rand.Reader, bits)
if err != nil {
return nil, nil, err
}
publicKey, err := ssh.NewPublicKey(&privateKey.PublicKey)
if err != nil {
return nil, nil, err
}
return privateKey, publicKey, nil
}
func SavePrivateKeyToFile(filename string, privateKey *rsa.PrivateKey) error {
privateKeyBytes := x509.MarshalPKCS1PrivateKey(privateKey)
privateKeyPEM := &pem.Block{
Type: "RSA PRIVATE KEY",
Bytes: privateKeyBytes,
}
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
err = pem.Encode(file, privateKeyPEM)
if err != nil {
return err
}
return nil
}
func SavePublicKeyToFile(filename string, publicKey ssh.PublicKey) error {
publicKeyBytes := ssh.MarshalAuthorizedKey(publicKey)
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
_, err = file.WriteString(string(publicKeyBytes))
if err != nil {
return err
}
return nil
}
func SSHConnectToRemoteServer(connectionDetails string) error {
privateKey, err := LoadPrivateKey(privateKeyPath)
if err != nil {
return err
}
config := &ssh.ClientConfig{
User: "username", // You will replace this with the actual username extracted from connectionDetails
Auth: []ssh.AuthMethod{
ssh.PublicKeys(privateKey),
},
// Other configuration options like HostKeyCallback, etc.
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// Extract username, host, and port from connectionDetails
parts := strings.Split(connectionDetails, "@")
if len(parts) != 2 {
return errors.New("invalid connection format")
}
username := parts[0]
hostPort := parts[1]
config.User = username // Set the actual username
// Connect to the remote server
client, err := ssh.Dial("tcp", hostPort, config)
if err != nil {
return err
}
defer client.Close()
// Now you have a connected SSH client to the remote server.
// You can use this client to perform remote commands or file transfers.
return nil
}
func LoadPrivateKey(path string) (ssh.Signer, error) {
keyBytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}
privateKeyBlock, _ := pem.Decode(keyBytes)
if privateKeyBlock == nil || privateKeyBlock.Type != "RSA PRIVATE KEY" {
return nil, errors.New("failed to decode valid private key")
}
privateKey, err := x509.ParsePKCS1PrivateKey(privateKeyBlock.Bytes)
if err != nil {
return nil, err
}
return ssh.NewSignerFromKey(privateKey)
}
func GetPublicKey() (string, error) {
publicKeyBytes, err := os.ReadFile(publicKeyPath)
if err != nil {
return "", err
}
return string(publicKeyBytes), nil
}

View File

@ -28,10 +28,15 @@ func main() {
if !ok { if !ok {
log.Fatal("Must set OpenAI token as env variable: OPENAI_TOKEN") log.Fatal("Must set OpenAI token as env variable: OPENAI_TOKEN")
} }
AllowedUserID, ok := os.LookupEnv("ADMIN_DISCORD_ID")
if !ok {
log.Fatal("Must set OpenAI token as env variable: ADMIN_DISCORD_ID")
}
bot.BotToken = botToken bot.BotToken = botToken
bot.CryptoToken = cryptoToken bot.CryptoToken = cryptoToken
bot.OpenAIToken = openAIToken bot.OpenAIToken = openAIToken
bot.AllowedUserID = AllowedUserID
bot.Run() bot.Run()
} }

View File

@ -8,7 +8,6 @@ import (
func Run() { func Run() {
app := pocketbase.New() app := pocketbase.New()
// Start the PocketBase server in a goroutine.
func() { func() {
if err := app.Start(); err != nil { if err := app.Start(); err != nil {
log.Fatal(err) log.Fatal(err)

Binary file not shown.

Binary file not shown.