feat: Add deployment side config-ssh options (#6613)

* feat: Allow setting deployment wide ssh config settings
* feat: config-ssh respects deployment ssh config
* The '.' is now configurable
* Move buildinfo into deployment.go
This commit is contained in:
Steven Masley
2023-03-16 13:03:37 -05:00
committed by GitHub
parent 25e8abd63e
commit fe247c86eb
18 changed files with 642 additions and 49 deletions

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"flag"
"fmt"
"math"
"net/http"
"os"
@ -160,6 +161,7 @@ type DeploymentValues struct {
DisablePasswordAuth clibase.Bool `json:"disable_password_auth,omitempty" typescript:",notnull"`
Support SupportConfig `json:"support,omitempty" typescript:",notnull"`
GitAuthProviders clibase.Struct[[]GitAuthConfig] `json:"git_auth,omitempty" typescript:",notnull"`
SSHConfig SSHConfig `json:"config_ssh,omitempty" typescript:",notnull"`
Config clibase.String `json:"config,omitempty" typescript:",notnull"`
WriteConfig clibase.Bool `json:"write_config,omitempty" typescript:",notnull"`
@ -168,6 +170,40 @@ type DeploymentValues struct {
Address clibase.HostPort `json:"address,omitempty" typescript:",notnull"`
}
// SSHConfig is configuration the cli & vscode extension use for configuring
// ssh connections.
type SSHConfig struct {
// DeploymentName is the config-ssh Hostname prefix
DeploymentName clibase.String
// SSHConfigOptions are additional options to add to the ssh config file.
// This will override defaults.
SSHConfigOptions clibase.Strings
}
func (c SSHConfig) ParseOptions() (map[string]string, error) {
m := make(map[string]string)
for _, opt := range c.SSHConfigOptions {
key, value, err := ParseSSHConfigOption(opt)
if err != nil {
return nil, err
}
m[key] = value
}
return m, nil
}
// ParseSSHConfigOption parses a single ssh config option into it's key/value pair.
func ParseSSHConfigOption(opt string) (key string, value string, err error) {
// An equal sign or whitespace is the separator between the key and value.
idx := strings.IndexFunc(opt, func(r rune) bool {
return r == ' ' || r == '='
})
if idx == -1 {
return "", "", fmt.Errorf("invalid config-ssh option %q", opt)
}
return opt[:idx], opt[idx+1:], nil
}
type DERP struct {
Server DERPServerConfig `json:"server" typescript:",notnull"`
Config DERPConfig `json:"config" typescript:",notnull"`
@ -390,6 +426,11 @@ when required by your organization's security policy.`,
deploymentGroupDangerous = clibase.Group{
Name: "⚠️ Dangerous",
}
deploymentGroupClient = clibase.Group{
Name: "Client",
Description: "These options change the behavior of how clients interact with the Coder. " +
"Clients include the coder cli, vs code extension, and the web UI.",
}
deploymentGroupConfig = clibase.Group{
Name: "Config",
Description: `Use a YAML configuration file when your server launch become unwieldy.`,
@ -1265,6 +1306,29 @@ when required by your organization's security policy.`,
Group: &deploymentGroupConfig,
Value: &c.Config,
},
{
Name: "SSH Host Prefix",
Description: "The SSH deployment prefix is used in the Host of the ssh config.",
Flag: "ssh-hostname-prefix",
Env: "SSH_HOSTNAME_PREFIX",
YAML: "sshHostnamePrefix",
Group: &deploymentGroupClient,
Value: &c.SSHConfig.DeploymentName,
Hidden: false,
Default: "coder.",
},
{
Name: "SSH Config Options",
Description: "These SSH config options will override the default SSH config options. " +
"Provide options in \"key=value\" or \"key value\" format separated by commas." +
"Using this incorrectly can break SSH to your deployment, use cautiously.",
Flag: "ssh-config-options",
Env: "SSH_CONFIG_OPTIONS",
YAML: "sshConfigOptions",
Group: &deploymentGroupClient,
Value: &c.SSHConfig.SSHConfigOptions,
Hidden: false,
},
{
Name: "Write Config",
Description: `
@ -1580,3 +1644,25 @@ type DeploymentStats struct {
Workspaces WorkspaceDeploymentStats `json:"workspaces"`
SessionCount SessionCountDeploymentStats `json:"session_count"`
}
type SSHConfigResponse struct {
HostnamePrefix string `json:"hostname_prefix"`
SSHConfigOptions map[string]string `json:"ssh_config_options"`
}
// SSHConfiguration returns information about the SSH configuration for the
// Coder instance.
func (c *Client) SSHConfiguration(ctx context.Context) (SSHConfigResponse, error) {
res, err := c.Request(ctx, http.MethodGet, "/api/v2/deployment/ssh", nil)
if err != nil {
return SSHConfigResponse{}, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return SSHConfigResponse{}, ReadBodyAsError(res)
}
var sshConfig SSHConfigResponse
return sshConfig, json.NewDecoder(res.Body).Decode(&sshConfig)
}