mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 06:28:11 +00:00
Add infisical ssh connect command
This commit is contained in:
+1
-1
@@ -12,7 +12,7 @@ require (
|
|||||||
github.com/fatih/semgroup v1.2.0
|
github.com/fatih/semgroup v1.2.0
|
||||||
github.com/gitleaks/go-gitdiff v0.8.0
|
github.com/gitleaks/go-gitdiff v0.8.0
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/infisical/go-sdk v0.5.1
|
github.com/infisical/go-sdk v0.5.3
|
||||||
github.com/infisical/infisical-kmip v0.3.5
|
github.com/infisical/infisical-kmip v0.3.5
|
||||||
github.com/mattn/go-isatty v0.0.20
|
github.com/mattn/go-isatty v0.0.20
|
||||||
github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a
|
github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a
|
||||||
|
|||||||
+2
-2
@@ -277,8 +277,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
|||||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/infisical/go-sdk v0.5.1 h1:bl0D4A6CmvfL8RwEQTcZh39nsxC6q3HSs76/4J8grWY=
|
github.com/infisical/go-sdk v0.5.3 h1:6qQCkxR1NqeoYu/6gL9BvQARr/apupX7+Ei5adCRTCU=
|
||||||
github.com/infisical/go-sdk v0.5.1/go.mod h1:ExjqFLRz7LSpZpGluqDLvFl6dFBLq5LKyLW7GBaMAIs=
|
github.com/infisical/go-sdk v0.5.3/go.mod h1:ExjqFLRz7LSpZpGluqDLvFl6dFBLq5LKyLW7GBaMAIs=
|
||||||
github.com/infisical/infisical-kmip v0.3.5 h1:QM3s0e18B+mYv3a9HQNjNAlbwZJBzXq5BAJM2scIeiE=
|
github.com/infisical/infisical-kmip v0.3.5 h1:QM3s0e18B+mYv3a9HQNjNAlbwZJBzXq5BAJM2scIeiE=
|
||||||
github.com/infisical/infisical-kmip v0.3.5/go.mod h1:bO1M4YtKyutNg1bREPmlyZspC5duSR7hyQ3lPmLzrIs=
|
github.com/infisical/infisical-kmip v0.3.5/go.mod h1:bO1M4YtKyutNg1bREPmlyZspC5duSR7hyQ3lPmLzrIs=
|
||||||
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
|
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
"github.com/Infisical/infisical-merge/packages/util"
|
"github.com/Infisical/infisical-merge/packages/util"
|
||||||
infisicalSdk "github.com/infisical/go-sdk"
|
infisicalSdk "github.com/infisical/go-sdk"
|
||||||
infisicalSdkUtil "github.com/infisical/go-sdk/packages/util"
|
infisicalSdkUtil "github.com/infisical/go-sdk/packages/util"
|
||||||
|
"github.com/manifoldco/promptui"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
@@ -48,6 +50,12 @@ var sshSignKeyCmd = &cobra.Command{
|
|||||||
Run: signKey,
|
Run: signKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var sshConnectCmd = &cobra.Command{
|
||||||
|
Use: "connect",
|
||||||
|
Short: "Connect to an SSH host using issued credentials",
|
||||||
|
Run: sshConnect,
|
||||||
|
}
|
||||||
|
|
||||||
var algoToFileName = map[infisicalSdkUtil.CertKeyAlgorithm]string{
|
var algoToFileName = map[infisicalSdkUtil.CertKeyAlgorithm]string{
|
||||||
infisicalSdkUtil.RSA2048: "id_rsa_2048",
|
infisicalSdkUtil.RSA2048: "id_rsa_2048",
|
||||||
infisicalSdkUtil.RSA4096: "id_rsa_4096",
|
infisicalSdkUtil.RSA4096: "id_rsa_4096",
|
||||||
@@ -595,6 +603,122 @@ func signKey(cmd *cobra.Command, args []string) {
|
|||||||
fmt.Println("Successfully wrote SSH certificate to:", signedKeyPath)
|
fmt.Println("Successfully wrote SSH certificate to:", signedKeyPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sshConnect(cmd *cobra.Command, args []string) {
|
||||||
|
token, err := util.GetInfisicalToken(cmd)
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Unable to parse token")
|
||||||
|
}
|
||||||
|
|
||||||
|
var infisicalToken string
|
||||||
|
if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) {
|
||||||
|
infisicalToken = token.Token
|
||||||
|
} else {
|
||||||
|
util.RequireLogin()
|
||||||
|
util.RequireLocalWorkspaceFile()
|
||||||
|
|
||||||
|
loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails(true)
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Unable to authenticate")
|
||||||
|
}
|
||||||
|
|
||||||
|
if loggedInUserDetails.LoginExpired {
|
||||||
|
util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again")
|
||||||
|
}
|
||||||
|
|
||||||
|
infisicalToken = loggedInUserDetails.UserCredentials.JTWToken
|
||||||
|
}
|
||||||
|
|
||||||
|
customHeaders, err := util.GetInfisicalCustomHeadersMap()
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Unable to get custom headers")
|
||||||
|
}
|
||||||
|
|
||||||
|
infisicalClient := infisicalSdk.NewInfisicalClient(context.Background(), infisicalSdk.Config{
|
||||||
|
SiteUrl: config.INFISICAL_URL,
|
||||||
|
UserAgent: api.USER_AGENT,
|
||||||
|
AutoTokenRefresh: false,
|
||||||
|
CustomHeaders: customHeaders,
|
||||||
|
})
|
||||||
|
infisicalClient.Auth().SetAccessToken(infisicalToken)
|
||||||
|
|
||||||
|
// Fetch SSH Hosts
|
||||||
|
hosts, err := infisicalClient.Ssh().GetSshHosts(infisicalSdk.GetSshHostsOptions{})
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Failed to fetch SSH hosts")
|
||||||
|
}
|
||||||
|
if len(hosts) == 0 {
|
||||||
|
util.PrintErrorMessageAndExit("You do not have access to any SSH hosts")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prompt to select host
|
||||||
|
hostNames := make([]string, len(hosts))
|
||||||
|
for i, h := range hosts {
|
||||||
|
hostNames[i] = h.Hostname
|
||||||
|
}
|
||||||
|
|
||||||
|
hostPrompt := promptui.Select{
|
||||||
|
Label: "Select an SSH Host",
|
||||||
|
Items: hostNames,
|
||||||
|
Size: 10,
|
||||||
|
}
|
||||||
|
hostIdx, _, err := hostPrompt.Run()
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Prompt failed")
|
||||||
|
}
|
||||||
|
selectedHost := hosts[hostIdx]
|
||||||
|
|
||||||
|
// Prompt to select login user
|
||||||
|
if len(selectedHost.LoginMappings) == 0 {
|
||||||
|
util.PrintErrorMessageAndExit("No login users available for selected host")
|
||||||
|
}
|
||||||
|
|
||||||
|
loginUsers := make([]string, len(selectedHost.LoginMappings))
|
||||||
|
for i, m := range selectedHost.LoginMappings {
|
||||||
|
loginUsers[i] = m.LoginUser
|
||||||
|
}
|
||||||
|
|
||||||
|
loginPrompt := promptui.Select{
|
||||||
|
Label: "Select Login User",
|
||||||
|
Items: loginUsers,
|
||||||
|
Size: 5,
|
||||||
|
}
|
||||||
|
loginIdx, _, err := loginPrompt.Run()
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Prompt failed")
|
||||||
|
}
|
||||||
|
selectedLoginUser := selectedHost.LoginMappings[loginIdx].LoginUser
|
||||||
|
|
||||||
|
// Issue SSH creds for host
|
||||||
|
creds, err := infisicalClient.Ssh().IssueCredentialsFromHost(selectedHost.ID, infisicalSdk.IssueSshCredsFromHostOptions{
|
||||||
|
LoginUser: selectedLoginUser,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Failed to issue SSH credentials")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load credentials into SSH agent
|
||||||
|
err = addCredentialsToAgent(creds.PrivateKey, creds.SignedKey)
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "Failed to add credentials to SSH agent")
|
||||||
|
}
|
||||||
|
fmt.Println("✔ SSH credentials successfully added to agent")
|
||||||
|
|
||||||
|
// Connect to host using system ssh and agent
|
||||||
|
target := fmt.Sprintf("%s@%s", selectedLoginUser, selectedHost.Hostname)
|
||||||
|
fmt.Printf("Connecting to %s...\n", target)
|
||||||
|
|
||||||
|
sshCmd := exec.Command("ssh", target)
|
||||||
|
sshCmd.Stdin = os.Stdin
|
||||||
|
sshCmd.Stdout = os.Stdout
|
||||||
|
sshCmd.Stderr = os.Stderr
|
||||||
|
|
||||||
|
err = sshCmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
util.HandleError(err, "SSH connection failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
sshSignKeyCmd.Flags().String("token", "", "Issue SSH certificate using machine identity access token")
|
sshSignKeyCmd.Flags().String("token", "", "Issue SSH certificate using machine identity access token")
|
||||||
sshSignKeyCmd.Flags().String("certificateTemplateId", "", "The ID of the SSH certificate template to issue the SSH certificate for")
|
sshSignKeyCmd.Flags().String("certificateTemplateId", "", "The ID of the SSH certificate template to issue the SSH certificate for")
|
||||||
@@ -617,5 +741,9 @@ func init() {
|
|||||||
sshIssueCredentialsCmd.Flags().String("outFilePath", "", "The path to write the SSH credentials to such as ~/.ssh, ./some_folder, ./some_folder/id_rsa-cert.pub. If not provided, the credentials will be saved to the current working directory")
|
sshIssueCredentialsCmd.Flags().String("outFilePath", "", "The path to write the SSH credentials to such as ~/.ssh, ./some_folder, ./some_folder/id_rsa-cert.pub. If not provided, the credentials will be saved to the current working directory")
|
||||||
sshIssueCredentialsCmd.Flags().Bool("addToAgent", false, "Whether to add issued SSH credentials to the SSH agent")
|
sshIssueCredentialsCmd.Flags().Bool("addToAgent", false, "Whether to add issued SSH credentials to the SSH agent")
|
||||||
sshCmd.AddCommand(sshIssueCredentialsCmd)
|
sshCmd.AddCommand(sshIssueCredentialsCmd)
|
||||||
|
|
||||||
|
sshConnectCmd.Flags().String("token", "", "Use a machine identity access token")
|
||||||
|
sshCmd.AddCommand(sshConnectCmd)
|
||||||
rootCmd.AddCommand(sshCmd)
|
rootCmd.AddCommand(sshCmd)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user