From 3004c9ca92b5fa0792f789928ea8fb7ebdda1545 Mon Sep 17 00:00:00 2001 From: Zac Bergquist Date: Mon, 24 Jun 2024 12:39:38 -0600 Subject: [PATCH] Quote the cert/key flags for app curl command (#43356) `tsh app login` will print an example curl command for webapps, but it doesn't quote the --cert and --key flags. As a result, you can't copy-paste the command if $TELEPORT_HOME contains spaces. --- tool/tsh/common/app.go | 40 ++++++++++++++++++------------------- tool/tsh/common/app_test.go | 26 ++++++++++++------------ 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/tool/tsh/common/app.go b/tool/tsh/common/app.go index cb40d148d6111..0e868afda628b 100644 --- a/tool/tsh/common/app.go +++ b/tool/tsh/common/app.go @@ -121,7 +121,7 @@ func printAppCommand(cf *CLIConf, tc *client.TeleportClient, app types.Applicati switch { case app.IsAWSConsole(): - return awsCliTpl.Execute(output, map[string]string{ + return awsLoginTemplate.Execute(output, map[string]string{ "awsAppName": app.GetName(), "awsCmd": "s3 ls", "awsRoleARN": routeToApp.AWSRoleARN, @@ -150,24 +150,24 @@ func printAppCommand(cf *CLIConf, tc *client.TeleportClient, app types.Applicati return trace.Wrap(err, "failed to automatically login with `az login` using identity %q; run with --debug for details", routeToApp.AzureIdentity) } - return azureCliTpl.Execute(output, map[string]string{ + return azureLoginTemplate.Execute(output, map[string]string{ "appName": app.GetName(), "identity": routeToApp.AzureIdentity, }) case app.IsGCP(): - return gcpCliTpl.Execute(output, map[string]string{ + return gcpLoginTemplate.Execute(output, map[string]string{ "appName": app.GetName(), "serviceAccount": routeToApp.GCPServiceAccount, }) case app.IsTCP(): - return appLoginTCPTpl.Execute(output, map[string]string{ + return tcpAppLoginTemplate.Execute(output, map[string]string{ "appName": app.GetName(), }) case localProxyRequiredForApp(tc): - return appLoginLocalProxyTpl.Execute(output, map[string]interface{}{ + return webAppLoginProxyTemplate.Execute(output, map[string]interface{}{ "appName": app.GetName(), }) @@ -191,7 +191,7 @@ func printAppCommand(cf *CLIConf, tc *client.TeleportClient, app types.Applicati if err != nil { return trace.Wrap(err) } - return appLoginTpl.Execute(output, map[string]interface{}{ + return webAppLoginTemplate.Execute(output, map[string]interface{}{ "appName": app.GetName(), "curlCmd": curlCmd, "insecure": cf.InsecureSkipVerify, @@ -199,9 +199,9 @@ func printAppCommand(cf *CLIConf, tc *client.TeleportClient, app types.Applicati } } -// appLoginTpl is the message that gets printed to a user upon successful login +// webAppLoginTemplate is the message that gets printed to a user upon successful login // into an HTTP application. -var appLoginTpl = template.Must(template.New("").Parse( +var webAppLoginTemplate = template.Must(template.New("").Parse( `Logged into app {{.appName}}. Example curl command: {{.curlCmd}}{{ if .insecure }} @@ -210,9 +210,9 @@ WARNING: tsh was called with --insecure, so this curl command will be unable to {{- end }} `)) -// appLoginLocalProxyTpl is the message that gets printed to a user upon successful login +// webAppLoginProxyTemplate is the message that gets printed to a user upon successful login // into an HTTP application and local proxy is required. -var appLoginLocalProxyTpl = template.Must(template.New("").Parse( +var webAppLoginProxyTemplate = template.Must(template.New("").Parse( `Logged into app {{.appName}}. Start the local proxy for it: tsh proxy app {{.appName}} -p 8080 @@ -222,9 +222,9 @@ Then connect to the application through this proxy: curl http://127.0.0.1:8080 `)) -// appLoginTCPTpl is the message that gets printed to a user upon successful +// tcpAppLoginTemplate is the message that gets printed to a user upon successful // login into a TCP application. -var appLoginTCPTpl = template.Must(template.New("").Parse( +var tcpAppLoginTemplate = template.Must(template.New("").Parse( `Logged into TCP app {{.appName}}. Start the local TCP proxy for it: tsh proxy app {{.appName}} @@ -232,9 +232,9 @@ var appLoginTCPTpl = template.Must(template.New("").Parse( Then connect to the application through this proxy. `)) -// awsCliTpl is the message that gets printed to a user upon successful login +// awsLoginTemplate is the message that gets printed to a user upon successful login // into an AWS Console application. -var awsCliTpl = template.Must(template.New("").Parse( +var awsLoginTemplate = template.Must(template.New("").Parse( `Logged into AWS app "{{.awsAppName}}". Your IAM role: @@ -247,17 +247,17 @@ Or start a local proxy: tsh proxy aws --app {{.awsAppName}} `)) -// azureCliTpl is the message that gets printed to a user upon successful login +// azureLoginTemplate is the message that gets printed to a user upon successful login // into an Azure application. -var azureCliTpl = template.Must(template.New("").Parse( +var azureLoginTemplate = template.Must(template.New("").Parse( `Logged into Azure app "{{.appName}}". Your identity: {{.identity}} Example Azure CLI command: tsh az vm list `)) -// gcpCliTpl is the message that gets printed to a user upon successful login +// gcpLoginTemplate is the message that gets printed to a user upon successful login // into a GCP application. -var gcpCliTpl = template.Must(template.New("").Parse( +var gcpLoginTemplate = template.Must(template.New("").Parse( `Logged into GCP app "{{.appName}}". Your service account: {{.serviceAccount}} Example command: tsh gcloud compute instances list @@ -385,8 +385,8 @@ func formatAppConfig(tc *client.TeleportClient, profile *client.ProfileStatus, r } curlCmd := fmt.Sprintf(`curl %s\ - --cert %v \ - --key %v \ + --cert %q \ + --key %q \ %v`, curlInsecureFlag, profile.AppCertPath(tc.SiteName, routeToApp.Name), diff --git a/tool/tsh/common/app_test.go b/tool/tsh/common/app_test.go index 76c6e54eedc1e..72b13180c59f9 100644 --- a/tool/tsh/common/app_test.go +++ b/tool/tsh/common/app_test.go @@ -397,8 +397,8 @@ func TestFormatAppConfig(t *testing.T) { tc: defaultTc, format: appFormatCURL, expected: `curl \ - --cert /test/dir/keys/alice-app/root/test-app-x509.pem \ - --key /test/dir/keys/alice \ + --cert "/test/dir/keys/alice-app/root/test-app-x509.pem" \ + --key "/test/dir/keys/alice" \ https://test-app.example.com:8443`, }, { @@ -407,8 +407,8 @@ func TestFormatAppConfig(t *testing.T) { format: appFormatCURL, insecure: true, expected: `curl --insecure \ - --cert /test/dir/keys/alice-app/root/test-app-x509.pem \ - --key /test/dir/keys/alice \ + --cert "/test/dir/keys/alice-app/root/test-app-x509.pem" \ + --key "/test/dir/keys/alice" \ https://test-app.example.com:8443`, }, { @@ -421,7 +421,7 @@ func TestFormatAppConfig(t *testing.T) { "ca": "/test/dir/keys/cas/root.pem", "cert": "/test/dir/keys/alice-app/root/test-app-x509.pem", "key": "/test/dir/keys/alice", - "curl": "curl \\\n --cert /test/dir/keys/alice-app/root/test-app-x509.pem \\\n --key /test/dir/keys/alice \\\n https://test-app.example.com:8443" + "curl": "curl \\\n --cert \"/test/dir/keys/alice-app/root/test-app-x509.pem\" \\\n --key \"/test/dir/keys/alice\" \\\n https://test-app.example.com:8443" } `, }, @@ -433,8 +433,8 @@ func TestFormatAppConfig(t *testing.T) { cert: /test/dir/keys/alice-app/root/test-app-x509.pem curl: |- curl \ - --cert /test/dir/keys/alice-app/root/test-app-x509.pem \ - --key /test/dir/keys/alice \ + --cert "/test/dir/keys/alice-app/root/test-app-x509.pem" \ + --key "/test/dir/keys/alice" \ https://test-app.example.com:8443 key: /test/dir/keys/alice name: test-app @@ -478,7 +478,7 @@ uri: https://test-app.example.com:8443 "ca": "/test/dir/keys/cas/root.pem", "cert": "/test/dir/keys/alice-app/root/test-app-x509.pem", "key": "/test/dir/keys/alice", - "curl": "curl \\\n --cert /test/dir/keys/alice-app/root/test-app-x509.pem \\\n --key /test/dir/keys/alice \\\n https://test-app.example.com:8443", + "curl": "curl \\\n --cert \"/test/dir/keys/alice-app/root/test-app-x509.pem\" \\\n --key \"/test/dir/keys/alice\" \\\n https://test-app.example.com:8443", "azure_identity": "/subscriptions/11111111-1111-1111-1111-111111111111/resourceGroups/my-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/teleport-azure" } `, @@ -493,8 +493,8 @@ ca: /test/dir/keys/cas/root.pem cert: /test/dir/keys/alice-app/root/test-app-x509.pem curl: |- curl \ - --cert /test/dir/keys/alice-app/root/test-app-x509.pem \ - --key /test/dir/keys/alice \ + --cert "/test/dir/keys/alice-app/root/test-app-x509.pem" \ + --key "/test/dir/keys/alice" \ https://test-app.example.com:8443 key: /test/dir/keys/alice name: test-app @@ -520,7 +520,7 @@ uri: https://test-app.example.com:8443 "ca": "/test/dir/keys/cas/root.pem", "cert": "/test/dir/keys/alice-app/root/test-app-x509.pem", "key": "/test/dir/keys/alice", - "curl": "curl \\\n --cert /test/dir/keys/alice-app/root/test-app-x509.pem \\\n --key /test/dir/keys/alice \\\n https://test-app.example.com:8443", + "curl": "curl \\\n --cert \"/test/dir/keys/alice-app/root/test-app-x509.pem\" \\\n --key \"/test/dir/keys/alice\" \\\n https://test-app.example.com:8443", "gcp_service_account": "dev@example-123456.iam.gserviceaccount.com" } `, @@ -534,8 +534,8 @@ uri: https://test-app.example.com:8443 cert: /test/dir/keys/alice-app/root/test-app-x509.pem curl: |- curl \ - --cert /test/dir/keys/alice-app/root/test-app-x509.pem \ - --key /test/dir/keys/alice \ + --cert "/test/dir/keys/alice-app/root/test-app-x509.pem" \ + --key "/test/dir/keys/alice" \ https://test-app.example.com:8443 gcp_service_account: dev@example-123456.iam.gserviceaccount.com key: /test/dir/keys/alice