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/gitleaks/go-gitdiff v0.8.0
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/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a
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.5 h1:rQSgWW+thZQ2WfIbOD5SBflqx3BUUSNlvuDZdexXMFk=
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/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+64 -54
View File
@@ -44,6 +44,13 @@ var sshSignKeyCmd = &cobra.Command{
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 {
switch algo {
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 {
switch certType {
case infisicalSdkUtil.UserCert, infisicalSdkUtil.HostCert:
@@ -92,8 +86,20 @@ func writeToFile(filePath string, content string, perm os.FileMode) error {
}
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
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")
@@ -103,21 +109,14 @@ func issueCredentials(cmd *cobra.Command, args []string) {
util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again")
}
infisicalToken = loggedInUserDetails.UserCredentials.JTWToken
}
projectId, err := cmd.Flags().GetString("projectId")
certificateTemplateId, err := cmd.Flags().GetString("certificateTemplateId")
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
if projectId == "" {
util.PrintErrorMessageAndExit("You must set the --projectId 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")
if certificateTemplateId == "" {
util.PrintErrorMessageAndExit("You must set the --certificateTemplateId flag")
}
principalsStr, err := cmd.Flags().GetString("principals")
@@ -125,6 +124,11 @@ func issueCredentials(cmd *cobra.Command, args []string) {
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
principals := strings.Split(principalsStr, ",")
for i, principal := range principals {
@@ -220,16 +224,16 @@ func issueCredentials(cmd *cobra.Command, args []string) {
} else if !info.IsDir() {
util.PrintErrorMessageAndExit("The provided --outFilePath is not a directory")
}
}
}
// Define file names based on key algorithm
fileName := getFileName(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm))
fileName := algoToFileName[infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)]
// Define file paths
privateKeyPath = filepath.Join(outputDir, fileName)
publicKeyPath = filepath.Join(outputDir, fileName+".pub")
signedKeyPath = filepath.Join(outputDir, fileName+"-cert.pub")
}
}
// If outFilePath ends with "-cert.pub", ensure the signedKeyPath is set
if strings.HasSuffix(outFilePath, "-cert.pub") {
@@ -252,8 +256,7 @@ func issueCredentials(cmd *cobra.Command, args []string) {
infisicalClient.Auth().SetAccessToken(infisicalToken)
creds, err := infisicalClient.Ssh().IssueCredentials(infisicalSdk.IssueSshCredsOptions{
ProjectID: projectId,
TemplateName: templateName,
CertificateTemplateID: certificateTemplateId,
Principals: principals,
KeyAlgorithm: infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm),
CertType: infisicalSdkUtil.SshCertType(certType),
@@ -267,12 +270,12 @@ func issueCredentials(cmd *cobra.Command, args []string) {
// If signedKeyPath wasn't set in the directory scenario, set it now
if signedKeyPath == "" {
fileName := getFileName(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm))
fileName := algoToFileName[infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)]
signedKeyPath = filepath.Join(outputDir, fileName+"-cert.pub")
}
if privateKeyPath == "" {
privateKeyPath = filepath.Join(outputDir, getFileName(infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)))
privateKeyPath = filepath.Join(outputDir, algoToFileName[infisicalSdkUtil.CertKeyAlgorithm(keyAlgorithm)])
}
err = writeToFile(privateKeyPath, creds.PrivateKey, 0600)
if err != nil {
@@ -292,12 +295,24 @@ func issueCredentials(cmd *cobra.Command, args []string) {
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) {
token, err := util.GetInfisicalToken(cmd)
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
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")
@@ -307,21 +322,14 @@ func signKey(cmd *cobra.Command, args []string) {
util.PrintErrorMessageAndExit("Your login session has expired, please run [infisical login] and try again")
}
infisicalToken = loggedInUserDetails.UserCredentials.JTWToken
}
projectId, err := cmd.Flags().GetString("projectId")
certificateTemplateId, err := cmd.Flags().GetString("certificateTemplateId")
if err != nil {
util.HandleError(err, "Unable to parse flag")
}
if projectId == "" {
util.PrintErrorMessageAndExit("You must set the --projectId 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")
if certificateTemplateId == "" {
util.PrintErrorMessageAndExit("You must set the --certificateTemplateId flag")
}
publicKey, err := cmd.Flags().GetString("publicKey")
@@ -365,7 +373,7 @@ func signKey(cmd *cobra.Command, args []string) {
publicKey = strings.TrimSpace(string(content))
}
if (strings.TrimSpace(publicKey) == "") {
if strings.TrimSpace(publicKey) == "" {
util.HandleError(fmt.Errorf("Public key is empty"), "Invalid input")
}
@@ -374,10 +382,13 @@ func signKey(cmd *cobra.Command, args []string) {
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
principals := strings.Split(principalsStr, ",")
// Trim whitespace around each principal
for i, principal := range principals {
principals[i] = strings.TrimSpace(principal)
}
@@ -419,7 +430,7 @@ func signKey(cmd *cobra.Command, args []string) {
}
// check if public key path exists
if (publicKeyFilePath == "") {
if publicKeyFilePath == "" {
util.PrintErrorMessageAndExit("--outFilePath must be specified when --publicKeyFilePath is not provided")
}
@@ -438,7 +449,7 @@ func signKey(cmd *cobra.Command, args []string) {
}
// 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")
}
@@ -472,8 +483,7 @@ func signKey(cmd *cobra.Command, args []string) {
infisicalClient.Auth().SetAccessToken(infisicalToken)
creds, err := infisicalClient.Ssh().SignKey(infisicalSdk.SignSshPublicKeyOptions{
ProjectID: projectId,
TemplateName: templateName,
CertificateTemplateID: certificateTemplateId,
PublicKey: publicKey,
Principals: principals,
CertType: infisicalSdkUtil.SshCertType(certType),
@@ -494,8 +504,8 @@ func signKey(cmd *cobra.Command, args []string) {
}
func init() {
sshSignKeyCmd.Flags().String("projectId", "", "The projectId to issue credentials for")
sshSignKeyCmd.Flags().String("templateName", "", "The template name to issue credentials for")
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("publicKey", "", "The public key 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")
@@ -505,8 +515,8 @@ func init() {
sshSignKeyCmd.Flags().String("keyId", "", "The keyId that the created certificate should have")
sshCmd.AddCommand(sshSignKeyCmd)
sshIssueCredentialsCmd.Flags().String("projectId", "", "The projectId to issue SSH credentials for")
sshIssueCredentialsCmd.Flags().String("templateName", "", "The template name to issue SSH credentials for")
sshIssueCredentialsCmd.Flags().String("token", "", "Issue SSH credentials using machine identity access token")
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("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")