Skip to content

Instantly share code, notes, and snippets.

@shohiebsense
Created May 6, 2023 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shohiebsense/7297df44472a4d81f96fbe48c3f63ba6 to your computer and use it in GitHub Desktop.
Save shohiebsense/7297df44472a4d81f96fbe48c3f63ba6 to your computer and use it in GitHub Desktop.
Gorm With SSH
import (
"context"
//"database/sql"
"fmt"
"log"
"net"
"os"
"github.com/go-sql-driver/mysql"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/agent"
gormMysql "gorm.io/driver/mysql"
"gorm.io/gorm"
)
type DatabaseCreds struct {
SSHHost string // SSH Server Hostname/IP
SSHPort int // SSH Port
SSHUser string // SSH Username
SSHKeyFile string // SSH Key file location
}
type ViaSSHDialer struct {
client *ssh.Client
}
func (self *ViaSSHDialer) Dial(addr string) (net.Conn, error) {
return self.client.Dial("tcp", addr)
}
//var DB *gorm.DB
var DBEPROC *gorm.DB
func ConnectToDb() {
var err error
sshConn, err := ConnectToDB(DatabaseCreds{
SSHHost: "0.0.0.0",
SSHPort: 22,
SSHUser: "usr",
SSHKeyFile: "your.pem",
})
//defer sshConn.Close()
if err != nil {
panic("failed to connect to db")
}
}
func ConnectToDB(dbCreds DatabaseCreds) (*ssh.Client, error) {
var agentClient agent.Agent
// Establish a connection to the local ssh-agent
if conn, err := net.Dial("unix", os.Getenv("SSH_AUTH_SOCK")); err == nil {
log.Println(err)
defer conn.Close()
// Create a new instance of the ssh agent
agentClient = agent.NewClient(conn)
}
pemBytes, err := os.ReadFile(dbCreds.SSHKeyFile)
if err != nil {
log.Println(err)
return nil, err
}
signer, err := ssh.ParsePrivateKeyWithPassphrase(pemBytes, []byte("passphrase"))
if err != nil {
log.Println(err)
return nil, err
}
// The client configuration with configuration option to use the ssh-agent
sshConfig := &ssh.ClientConfig{
User: dbCreds.SSHUser,
Auth: []ssh.AuthMethod{ssh.PublicKeys(signer)},
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}
// When the agentClient connection succeeded, add them as AuthMethod
if agentClient != nil {
sshConfig.Auth = append(sshConfig.Auth, ssh.PublicKeysCallback(agentClient.Signers))
}
// Connect to the SSH Server
sshConn, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", dbCreds.SSHHost, dbCreds.SSHPort), sshConfig)
if err != nil {
log.Println(err)
return nil, err
}
// Now we register the ViaSSHDialer with the ssh connection as a parameter
mysql.RegisterDialContext("mysql+tcp", func(_ context.Context, addr string) (net.Conn, error) {
dialer := &ViaSSHDialer{sshConn}
return dialer.Dial(addr)
})
dsn := os.Getenv("DB_EPROC")
DBEPROC, err = gorm.Open(gormMysql.Open(dsn), &gorm.Config{})
if err != nil {
println(err)
return sshConn, err
}
fmt.Println("Successfully connected to the db")
return sshConn, err
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment