Update ssh cli issue/sign according to review

This commit is contained in:
Tuan Dang
2024-12-17 13:12:47 -08:00
parent be36827392
commit 765280eef6
3 changed files with 227 additions and 215 deletions
+1 -1
View File
@@ -10,7 +10,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.4.5 github.com/infisical/go-sdk v0.4.6
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
github.com/muesli/mango-cobra v1.2.0 github.com/muesli/mango-cobra v1.2.0
+2
View File
@@ -269,6 +269,8 @@ github.com/infisical/go-sdk v0.4.3 h1:O5ZJ2eCBAZDE9PIAfBPq9Utb2CgQKrhmj9R0oFTRu4
github.com/infisical/go-sdk v0.4.3/go.mod h1:6fWzAwTPIoKU49mQ2Oxu+aFnJu9n7k2JcNrZjzhHM2M= github.com/infisical/go-sdk v0.4.3/go.mod h1:6fWzAwTPIoKU49mQ2Oxu+aFnJu9n7k2JcNrZjzhHM2M=
github.com/infisical/go-sdk v0.4.5 h1:rQSgWW+thZQ2WfIbOD5SBflqx3BUUSNlvuDZdexXMFk= github.com/infisical/go-sdk v0.4.5 h1:rQSgWW+thZQ2WfIbOD5SBflqx3BUUSNlvuDZdexXMFk=
github.com/infisical/go-sdk v0.4.5/go.mod h1:6fWzAwTPIoKU49mQ2Oxu+aFnJu9n7k2JcNrZjzhHM2M= github.com/infisical/go-sdk v0.4.5/go.mod h1:6fWzAwTPIoKU49mQ2Oxu+aFnJu9n7k2JcNrZjzhHM2M=
github.com/infisical/go-sdk v0.4.6 h1:RXXcmucfO2T5dSzXao9h9pZVn+m2usuflVO45Lpoz/o=
github.com/infisical/go-sdk v0.4.6/go.mod h1:6fWzAwTPIoKU49mQ2Oxu+aFnJu9n7k2JcNrZjzhHM2M=
github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo=
github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+224 -214
View File
@@ -44,6 +44,13 @@ var sshSignKeyCmd = &cobra.Command{
Run: signKey, Run: signKey,
} }
var algoToFileName = map[infisicalSdkUtil.CertKeyAlgorithm]string{
infisicalSdkUtil.RSA2048: "id_rsa_2048",
infisicalSdkUtil.RSA4096: "id_rsa_4096",
infisicalSdkUtil.ECDSAP256: "id_ecdsa_p256",
infisicalSdkUtil.ECDSAP384: "id_ecdsa_p384",
}
func isValidKeyAlgorithm(algo infisicalSdkUtil.CertKeyAlgorithm) bool { func isValidKeyAlgorithm(algo infisicalSdkUtil.CertKeyAlgorithm) bool {
switch algo { switch algo {
case infisicalSdkUtil.RSA2048, infisicalSdkUtil.RSA4096, infisicalSdkUtil.ECDSAP256, infisicalSdkUtil.ECDSAP384: case infisicalSdkUtil.RSA2048, infisicalSdkUtil.RSA4096, infisicalSdkUtil.ECDSAP256, infisicalSdkUtil.ECDSAP384:
@@ -53,19 +60,6 @@ func isValidKeyAlgorithm(algo infisicalSdkUtil.CertKeyAlgorithm) bool {
} }
} }
func getFileName(algo infisicalSdkUtil.CertKeyAlgorithm) string {
switch algo {
case infisicalSdkUtil.RSA2048:
return "id_rsa_2048"
case infisicalSdkUtil.RSA4096:
return "id_rsa_4096"
case infisicalSdkUtil.ECDSAP256:
return "id_ecdsa_p256"
default:
return "id_ecdsa_p384"
}
}
func isValidCertType(certType infisicalSdkUtil.SshCertType) bool { func isValidCertType(certType infisicalSdkUtil.SshCertType) bool {
switch certType { switch certType {
case infisicalSdkUtil.UserCert, infisicalSdkUtil.HostCert: case infisicalSdkUtil.UserCert, infisicalSdkUtil.HostCert:
@@ -76,48 +70,53 @@ func isValidCertType(certType infisicalSdkUtil.SshCertType) bool {
} }
func writeToFile(filePath string, content string, perm os.FileMode) error { func writeToFile(filePath string, content string, perm os.FileMode) error {
// Ensure the directory exists // Ensure the directory exists
dir := filepath.Dir(filePath) dir := filepath.Dir(filePath)
if err := os.MkdirAll(dir, 0755); err != nil { if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err) return fmt.Errorf("failed to create directory %s: %w", dir, err)
} }
// Write the content to the file // Write the content to the file
err := os.WriteFile(filePath, []byte(content), perm) err := os.WriteFile(filePath, []byte(content), perm)
if err != nil { if err != nil {
return fmt.Errorf("failed to write to file %s: %w", filePath, err) return fmt.Errorf("failed to write to file %s: %w", filePath, err)
} }
return nil return nil
} }
func issueCredentials(cmd *cobra.Command, args []string) { func issueCredentials(cmd *cobra.Command, args []string) {
token, err := util.GetInfisicalToken(cmd)
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
var infisicalToken string var infisicalToken string
util.RequireLogin()
loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails(true) if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) {
if err != nil { infisicalToken = token.Token
util.HandleError(err, "Unable to authenticate") } 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
} }
if loggedInUserDetails.LoginExpired { certificateTemplateId, err := cmd.Flags().GetString("certificateTemplateId")
util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again")
}
infisicalToken = loggedInUserDetails.UserCredentials.JTWToken
projectId, err := cmd.Flags().GetString("projectId")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
if projectId == "" { if certificateTemplateId == "" {
util.PrintErrorMessageAndExit("You must set the --projectId flag") util.PrintErrorMessageAndExit("You must set the --certificateTemplateId flag")
}
templateName, err := cmd.Flags().GetString("templateName")
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
if templateName == "" {
util.PrintErrorMessageAndExit("You must set the --templateName flag")
} }
principalsStr, err := cmd.Flags().GetString("principals") principalsStr, err := cmd.Flags().GetString("principals")
@@ -125,6 +124,11 @@ func issueCredentials(cmd *cobra.Command, args []string) {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
// Check if the input string is empty before splitting
if principalsStr == "" {
util.HandleError(fmt.Errorf("no principals provided"), "The 'principals' flag cannot be empty")
}
// Convert the comma-delimited string into a slice of strings // Convert the comma-delimited string into a slice of strings
principals := strings.Split(principalsStr, ",") principals := strings.Split(principalsStr, ",")
for i, principal := range principals { for i, principal := range principals {
@@ -137,112 +141,112 @@ func issueCredentials(cmd *cobra.Command, args []string) {
} }
if !isValidKeyAlgorithm(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)) { if !isValidKeyAlgorithm(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)) {
util.HandleError(fmt.Errorf("invalid keyAlgorithm: %s", keyAlgorithm), util.HandleError(fmt.Errorf("invalid keyAlgorithm: %s", keyAlgorithm),
"Valid values: RSA_2048, RSA_4096, EC_prime256v1, EC_secp384r1") "Valid values: RSA_2048, RSA_4096, EC_prime256v1, EC_secp384r1")
} }
certType, err := cmd.Flags().GetString("certType") certType, err := cmd.Flags().GetString("certType")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
if !isValidCertType(infisicalSdkUtil.SshCertType(certType)) { if !isValidCertType(infisicalSdkUtil.SshCertType(certType)) {
util.HandleError(fmt.Errorf("invalid certType: %s", certType), util.HandleError(fmt.Errorf("invalid certType: %s", certType),
"Valid values: user, host") "Valid values: user, host")
} }
ttl, err := cmd.Flags().GetString("ttl") ttl, err := cmd.Flags().GetString("ttl")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
keyId, err := cmd.Flags().GetString("keyId") keyId, err := cmd.Flags().GetString("keyId")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
outFilePath, err := cmd.Flags().GetString("outFilePath") outFilePath, err := cmd.Flags().GetString("outFilePath")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
var ( var (
outputDir string outputDir string
privateKeyPath string privateKeyPath string
publicKeyPath string publicKeyPath string
signedKeyPath string signedKeyPath string
) )
if outFilePath == "" { if outFilePath == "" {
// Use current working directory // Use current working directory
cwd, err := os.Getwd() cwd, err := os.Getwd()
if err != nil { if err != nil {
util.HandleError(err, "Failed to get current working directory") util.HandleError(err, "Failed to get current working directory")
} }
outputDir = cwd outputDir = cwd
} else { } else {
// Expand ~ to home directory if present // Expand ~ to home directory if present
if strings.HasPrefix(outFilePath, "~") { if strings.HasPrefix(outFilePath, "~") {
homeDir, err := os.UserHomeDir() homeDir, err := os.UserHomeDir()
if err != nil { if err != nil {
util.HandleError(err, "Failed to resolve home directory") util.HandleError(err, "Failed to resolve home directory")
} }
outFilePath = strings.Replace(outFilePath, "~", homeDir, 1) outFilePath = strings.Replace(outFilePath, "~", homeDir, 1)
} }
// Check if outFilePath ends with "-cert.pub" // Check if outFilePath ends with "-cert.pub"
if strings.HasSuffix(outFilePath, "-cert.pub") { if strings.HasSuffix(outFilePath, "-cert.pub") {
// Treat outFilePath as the signed key path // Treat outFilePath as the signed key path
signedKeyPath = outFilePath signedKeyPath = outFilePath
// Derive the base name by removing "-cert.pub" // Derive the base name by removing "-cert.pub"
baseName := strings.TrimSuffix(filepath.Base(outFilePath), "-cert.pub") baseName := strings.TrimSuffix(filepath.Base(outFilePath), "-cert.pub")
// Set the output directory // Set the output directory
outputDir = filepath.Dir(outFilePath) outputDir = filepath.Dir(outFilePath)
// Define private and public key paths // Define private and public key paths
privateKeyPath = filepath.Join(outputDir, baseName) privateKeyPath = filepath.Join(outputDir, baseName)
publicKeyPath = filepath.Join(outputDir, baseName+".pub") publicKeyPath = filepath.Join(outputDir, baseName+".pub")
} else { } else {
// Treat outFilePath as a directory // Treat outFilePath as a directory
outputDir = outFilePath outputDir = outFilePath
// Check if the directory exists; if not, create it // Check if the directory exists; if not, create it
info, err := os.Stat(outputDir) info, err := os.Stat(outputDir)
if os.IsNotExist(err) { if os.IsNotExist(err) {
err = os.MkdirAll(outputDir, 0755) err = os.MkdirAll(outputDir, 0755)
if err != nil { if err != nil {
util.HandleError(err, "Failed to create output directory") util.HandleError(err, "Failed to create output directory")
} }
} else if err != nil { } else if err != nil {
util.HandleError(err, "Failed to access output directory") util.HandleError(err, "Failed to access output directory")
} else if !info.IsDir() { } else if !info.IsDir() {
util.PrintErrorMessageAndExit("The provided --outFilePath is not a directory") util.PrintErrorMessageAndExit("The provided --outFilePath is not a directory")
} }
}
}
// Define file names based on key algorithm // Define file names based on key algorithm
fileName := getFileName(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)) fileName := algoToFileName[infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)]
// Define file paths // Define file paths
privateKeyPath = filepath.Join(outputDir, fileName) privateKeyPath = filepath.Join(outputDir, fileName)
publicKeyPath = filepath.Join(outputDir, fileName+".pub") publicKeyPath = filepath.Join(outputDir, fileName+".pub")
signedKeyPath = filepath.Join(outputDir, fileName+"-cert.pub") signedKeyPath = filepath.Join(outputDir, fileName+"-cert.pub")
}
}
// If outFilePath ends with "-cert.pub", ensure the signedKeyPath is set // If outFilePath ends with "-cert.pub", ensure the signedKeyPath is set
if strings.HasSuffix(outFilePath, "-cert.pub") { if strings.HasSuffix(outFilePath, "-cert.pub") {
// Ensure the signedKeyPath was set // Ensure the signedKeyPath was set
if signedKeyPath == "" { if signedKeyPath == "" {
util.HandleError(fmt.Errorf("signedKeyPath is not set correctly"), "Internal error") util.HandleError(fmt.Errorf("signedKeyPath is not set correctly"), "Internal error")
} }
} else { } else {
// Ensure all paths are set // Ensure all paths are set
if privateKeyPath == "" || publicKeyPath == "" || signedKeyPath == "" { if privateKeyPath == "" || publicKeyPath == "" || signedKeyPath == "" {
util.HandleError(fmt.Errorf("file paths are not set correctly"), "Internal error") util.HandleError(fmt.Errorf("file paths are not set correctly"), "Internal error")
} }
} }
infisicalClient := infisicalSdk.NewInfisicalClient(context.Background(), infisicalSdk.Config{ infisicalClient := infisicalSdk.NewInfisicalClient(context.Background(), infisicalSdk.Config{
SiteUrl: config.INFISICAL_URL, SiteUrl: config.INFISICAL_URL,
@@ -252,83 +256,87 @@ func issueCredentials(cmd *cobra.Command, args []string) {
infisicalClient.Auth().SetAccessToken(infisicalToken) infisicalClient.Auth().SetAccessToken(infisicalToken)
creds, err := infisicalClient.Ssh().IssueCredentials(infisicalSdk.IssueSshCredsOptions{ creds, err := infisicalClient.Ssh().IssueCredentials(infisicalSdk.IssueSshCredsOptions{
ProjectID: projectId, CertificateTemplateID: certificateTemplateId,
TemplateName: templateName, Principals: principals,
Principals: principals, KeyAlgorithm: infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm),
KeyAlgorithm: infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm), CertType: infisicalSdkUtil.SshCertType(certType),
CertType: infisicalSdkUtil.SshCertType(certType), TTL: ttl,
TTL: ttl, KeyID: keyId,
KeyID: keyId,
}) })
if err != nil { if err != nil {
util.HandleError(err, "To issue SSH credentials") util.HandleError(err, "To issue SSH credentials")
} }
// If signedKeyPath wasn't set in the directory scenario, set it now // If signedKeyPath wasn't set in the directory scenario, set it now
if signedKeyPath == "" { if signedKeyPath == "" {
fileName := getFileName(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)) fileName := algoToFileName[infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)]
signedKeyPath = filepath.Join(outputDir, fileName + "-cert.pub") signedKeyPath = filepath.Join(outputDir, fileName+"-cert.pub")
} }
if privateKeyPath == "" { if privateKeyPath == "" {
privateKeyPath = filepath.Join(outputDir, getFileName(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm))) privateKeyPath = filepath.Join(outputDir, algoToFileName[infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)])
} }
err = writeToFile(privateKeyPath, creds.PrivateKey, 0600) err = writeToFile(privateKeyPath, creds.PrivateKey, 0600)
if err != nil { if err != nil {
util.HandleError(err, "Failed to write Private Key to file") util.HandleError(err, "Failed to write Private Key to file")
} }
if publicKeyPath == "" { if publicKeyPath == "" {
publicKeyPath = privateKeyPath + ".pub" publicKeyPath = privateKeyPath + ".pub"
} }
err = writeToFile(publicKeyPath, creds.PublicKey, 0644) err = writeToFile(publicKeyPath, creds.PublicKey, 0644)
if err != nil { if err != nil {
util.HandleError(err, "Failed to write Public Key to file") util.HandleError(err, "Failed to write Public Key to file")
} }
err = writeToFile(signedKeyPath, creds.SignedKey, 0644) err = writeToFile(signedKeyPath, creds.SignedKey, 0644)
if err != nil { if err != nil {
util.HandleError(err, "Failed to write Signed Key to file") util.HandleError(err, "Failed to write Signed Key to file")
} }
fmt.Println("Successfully wrote SSH certificate tox:", signedKeyPath) fmt.Println("Successfully wrote SSH certificate to:", signedKeyPath)
} }
func signKey(cmd *cobra.Command, args []string) { func signKey(cmd *cobra.Command, args []string) {
token, err := util.GetInfisicalToken(cmd)
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
var infisicalToken string var infisicalToken string
util.RequireLogin()
loggedInUserDetails, err := util.GetCurrentLoggedInUserDetails(true) if token != nil && (token.Type == util.SERVICE_TOKEN_IDENTIFIER || token.Type == util.UNIVERSAL_AUTH_TOKEN_IDENTIFIER) {
if err != nil { infisicalToken = token.Token
util.HandleError(err, "Unable to authenticate") } 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
} }
if loggedInUserDetails.LoginExpired { certificateTemplateId, err := cmd.Flags().GetString("certificateTemplateId")
util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again")
}
infisicalToken = loggedInUserDetails.UserCredentials.JTWToken
projectId, err := cmd.Flags().GetString("projectId")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
if projectId == "" { if certificateTemplateId == "" {
util.PrintErrorMessageAndExit("You must set the --projectId flag") util.PrintErrorMessageAndExit("You must set the --certificateTemplateId flag")
} }
templateName, err := cmd.Flags().GetString("templateName")
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
if templateName == "" {
util.PrintErrorMessageAndExit("You must set the --templateName flag")
}
publicKey, err := cmd.Flags().GetString("publicKey") publicKey, err := cmd.Flags().GetString("publicKey")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
publicKeyFilePath, err := cmd.Flags().GetString("publicKeyFilePath") publicKeyFilePath, err := cmd.Flags().GetString("publicKeyFilePath")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
@@ -356,7 +364,7 @@ func signKey(cmd *cobra.Command, args []string) {
if !strings.HasSuffix(publicKeyFilePath, ".pub") { if !strings.HasSuffix(publicKeyFilePath, ".pub") {
util.HandleError(fmt.Errorf("public key file must have a .pub extension"), "Invalid input") util.HandleError(fmt.Errorf("public key file must have a .pub extension"), "Invalid input")
} }
content, err := os.ReadFile(publicKeyFilePath) content, err := os.ReadFile(publicKeyFilePath)
if err != nil { if err != nil {
util.HandleError(err, "Failed to read public key file") util.HandleError(err, "Failed to read public key file")
@@ -365,7 +373,7 @@ func signKey(cmd *cobra.Command, args []string) {
publicKey = strings.TrimSpace(string(content)) publicKey = strings.TrimSpace(string(content))
} }
if (strings.TrimSpace(publicKey) == "") { if strings.TrimSpace(publicKey) == "" {
util.HandleError(fmt.Errorf("Public key is empty"), "Invalid input") util.HandleError(fmt.Errorf("Public key is empty"), "Invalid input")
} }
@@ -374,29 +382,32 @@ func signKey(cmd *cobra.Command, args []string) {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
// Check if the input string is empty before splitting
if principalsStr == "" {
util.HandleError(fmt.Errorf("no principals provided"), "The 'principals' flag cannot be empty")
}
// Convert the comma-delimited string into a slice of strings // Convert the comma-delimited string into a slice of strings
principals := strings.Split(principalsStr, ",") principals := strings.Split(principalsStr, ",")
// Trim whitespace around each principal
for i, principal := range principals { for i, principal := range principals {
principals[i] = strings.TrimSpace(principal) principals[i] = strings.TrimSpace(principal)
} }
certType, err := cmd.Flags().GetString("certType") certType, err := cmd.Flags().GetString("certType")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
if !isValidCertType(infisicalSdkUtil.SshCertType(certType)) { if !isValidCertType(infisicalSdkUtil.SshCertType(certType)) {
util.HandleError(fmt.Errorf("invalid certType: %s", certType), util.HandleError(fmt.Errorf("invalid certType: %s", certType),
"Valid values: user, host") "Valid values: user, host")
} }
ttl, err := cmd.Flags().GetString("ttl") ttl, err := cmd.Flags().GetString("ttl")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
keyId, err := cmd.Flags().GetString("keyId") keyId, err := cmd.Flags().GetString("keyId")
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
@@ -406,39 +417,39 @@ func signKey(cmd *cobra.Command, args []string) {
if err != nil { if err != nil {
util.HandleError(err, "Unable to parse flag") util.HandleError(err, "Unable to parse flag")
} }
var ( var (
outputDir string outputDir string
signedKeyPath string signedKeyPath string
) )
if outFilePath == "" { if outFilePath == "" {
// Use current working directory // Use current working directory
if err != nil { if err != nil {
util.HandleError(err, "Failed to get current working directory") util.HandleError(err, "Failed to get current working directory")
}
// check if public key path exists
if (publicKeyFilePath == "") {
util.PrintErrorMessageAndExit("--outFilePath must be specified when --publicKeyFilePath is not provided")
} }
// check if public key path exists
if publicKeyFilePath == "" {
util.PrintErrorMessageAndExit("--outFilePath must be specified when --publicKeyFilePath is not provided")
}
outputDir = filepath.Dir(publicKeyFilePath) outputDir = filepath.Dir(publicKeyFilePath)
// Derive the base name by removing "-cert.pub" // Derive the base name by removing "-cert.pub"
baseName := strings.TrimSuffix(filepath.Base(publicKeyFilePath), ".pub") baseName := strings.TrimSuffix(filepath.Base(publicKeyFilePath), ".pub")
signedKeyPath = filepath.Join(outputDir, baseName + "-cert.pub") signedKeyPath = filepath.Join(outputDir, baseName+"-cert.pub")
} else { } else {
// Expand ~ to home directory if present // Expand ~ to home directory if present
if strings.HasPrefix(outFilePath, "~") { if strings.HasPrefix(outFilePath, "~") {
homeDir, err := os.UserHomeDir() homeDir, err := os.UserHomeDir()
if err != nil { if err != nil {
util.HandleError(err, "Failed to resolve home directory") util.HandleError(err, "Failed to resolve home directory")
} }
outFilePath = strings.Replace(outFilePath, "~", homeDir, 1) outFilePath = strings.Replace(outFilePath, "~", homeDir, 1)
} }
// Check if outFilePath ends with "-cert.pub" // Check if outFilePath ends with "-cert.pub"
if (!strings.HasSuffix(outFilePath, "-cert.pub")) { if !strings.HasSuffix(outFilePath, "-cert.pub") {
util.PrintErrorMessageAndExit("--outFilePath must end with -cert.pub") util.PrintErrorMessageAndExit("--outFilePath must end with -cert.pub")
} }
@@ -472,13 +483,12 @@ func signKey(cmd *cobra.Command, args []string) {
infisicalClient.Auth().SetAccessToken(infisicalToken) infisicalClient.Auth().SetAccessToken(infisicalToken)
creds, err := infisicalClient.Ssh().SignKey(infisicalSdk.SignSshPublicKeyOptions{ creds, err := infisicalClient.Ssh().SignKey(infisicalSdk.SignSshPublicKeyOptions{
ProjectID: projectId, CertificateTemplateID: certificateTemplateId,
TemplateName: templateName, PublicKey: publicKey,
PublicKey: publicKey, Principals: principals,
Principals: principals, CertType: infisicalSdkUtil.SshCertType(certType),
CertType: infisicalSdkUtil.SshCertType(certType), TTL: ttl,
TTL: ttl, KeyID: keyId,
KeyID: keyId,
}) })
if err != nil { if err != nil {
@@ -486,16 +496,16 @@ func signKey(cmd *cobra.Command, args []string) {
} }
err = writeToFile(signedKeyPath, creds.SignedKey, 0644) err = writeToFile(signedKeyPath, creds.SignedKey, 0644)
if err != nil { if err != nil {
util.HandleError(err, "Failed to write Signed Key to file") util.HandleError(err, "Failed to write Signed Key to file")
} }
fmt.Println("Successfully wrote SSH certificate to:", signedKeyPath) fmt.Println("Successfully wrote SSH certificate to:", signedKeyPath)
} }
func init() { func init() {
sshSignKeyCmd.Flags().String("projectId", "", "The projectId to issue credentials for") sshSignKeyCmd.Flags().String("token", "", "Issue SSH certificate using machine identity access token")
sshSignKeyCmd.Flags().String("templateName", "", "The template name to issue credentials for") sshSignKeyCmd.Flags().String("certificateTemplateId", "", "The ID of the SSH certificate template to issue the SSH certificate for")
sshSignKeyCmd.Flags().String("publicKey", "", "The public key to sign") sshSignKeyCmd.Flags().String("publicKey", "", "The public key to sign")
sshSignKeyCmd.Flags().String("publicKeyFilePath", "", "The file path to the public key file to sign") sshSignKeyCmd.Flags().String("publicKeyFilePath", "", "The file path to the public key file to sign")
sshSignKeyCmd.Flags().String("outFilePath", "", "The path to write the SSH certificate to such as ~/.ssh/id_rsa-cert.pub. If not provided, the credentials will be saved to the directory of the specified public key file path or the current working directory") sshSignKeyCmd.Flags().String("outFilePath", "", "The path to write the SSH certificate to such as ~/.ssh/id_rsa-cert.pub. If not provided, the credentials will be saved to the directory of the specified public key file path or the current working directory")
@@ -505,8 +515,8 @@ func init() {
sshSignKeyCmd.Flags().String("keyId", "", "The keyId that the created certificate should have") sshSignKeyCmd.Flags().String("keyId", "", "The keyId that the created certificate should have")
sshCmd.AddCommand(sshSignKeyCmd) sshCmd.AddCommand(sshSignKeyCmd)
sshIssueCredentialsCmd.Flags().String("projectId", "", "The projectId to issue SSH credentials for") sshIssueCredentialsCmd.Flags().String("token", "", "Issue SSH credentials using machine identity access token")
sshIssueCredentialsCmd.Flags().String("templateName", "", "The template name to issue SSH credentials for") sshIssueCredentialsCmd.Flags().String("certificateTemplateId", "", "The ID of the SSH certificate template to issue SSH credentials for")
sshIssueCredentialsCmd.Flags().String("principals", "", "The principals to issue SSH credentials for") sshIssueCredentialsCmd.Flags().String("principals", "", "The principals to issue SSH credentials for")
sshIssueCredentialsCmd.Flags().String("keyAlgorithm", string(infisicalSdkUtil.RSA2048), "The key algorithm to issue SSH credentials for") sshIssueCredentialsCmd.Flags().String("keyAlgorithm", string(infisicalSdkUtil.RSA2048), "The key algorithm to issue SSH credentials for")
sshIssueCredentialsCmd.Flags().String("certType", string(infisicalSdkUtil.UserCert), "The cert type to issue SSH credentials for") sshIssueCredentialsCmd.Flags().String("certType", string(infisicalSdkUtil.UserCert), "The cert type to issue SSH credentials for")
@@ -515,4 +525,4 @@ 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")
sshCmd.AddCommand(sshIssueCredentialsCmd) sshCmd.AddCommand(sshIssueCredentialsCmd)
rootCmd.AddCommand(sshCmd) rootCmd.AddCommand(sshCmd)
} }