mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-07-05 05:24:01 +00:00
feat(provider): add SOCKS5 proxy support for SSH connections (#970)
* feat(provider): add support for SOCKS5 proxy for SSH connection. Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> * fix: linter Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com> --------- Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
14836b6c50
commit
da1d7804af
@ -213,9 +213,27 @@ provider "proxmox" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### SSH Connection via SOCKS5 Proxy
|
||||||
|
|
||||||
|
The provider supports SSH connection to the target node via a SOCKS5 proxy.
|
||||||
|
|
||||||
|
To enable the SOCKS5 proxy, you need to configure the `ssh` block in the `provider` block, and specify the `socks5_server` argument:
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
provider "proxmox" {
|
||||||
|
// ...
|
||||||
|
ssh {
|
||||||
|
// ...
|
||||||
|
socks5_server = "ip-or-fqdn-of-socks5-server:port"
|
||||||
|
socks5_username = "username" # optional
|
||||||
|
socks5_password = "password" # optional
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
If enabled, this method will be used for all SSH connections to the target nodes in the cluster.
|
||||||
|
|
||||||
## API Token Authentication
|
## API Token Authentication
|
||||||
|
|
||||||
API Token authentication can be used to authenticate with the Proxmox API without the need to provide a password.
|
API Token authentication can be used to authenticate with the Proxmox API without the need to provide a password.
|
||||||
@ -296,6 +314,9 @@ In addition to [generic provider arguments](https://www.terraform.io/docs/config
|
|||||||
- `password` - (Optional) The password to use for the SSH connection. Defaults to the password used for the Proxmox API connection. Can also be sourced from `PROXMOX_VE_SSH_PASSWORD`.
|
- `password` - (Optional) The password to use for the SSH connection. Defaults to the password used for the Proxmox API connection. Can also be sourced from `PROXMOX_VE_SSH_PASSWORD`.
|
||||||
- `agent` - (Optional) Whether to use the SSH agent for the SSH authentication. Defaults to `false`. Can also be sourced from `PROXMOX_VE_SSH_AGENT`.
|
- `agent` - (Optional) Whether to use the SSH agent for the SSH authentication. Defaults to `false`. Can also be sourced from `PROXMOX_VE_SSH_AGENT`.
|
||||||
- `agent_socket` - (Optional) The path to the SSH agent socket. Defaults to the value of the `SSH_AUTH_SOCK` environment variable. Can also be sourced from `PROXMOX_VE_SSH_AUTH_SOCK`.
|
- `agent_socket` - (Optional) The path to the SSH agent socket. Defaults to the value of the `SSH_AUTH_SOCK` environment variable. Can also be sourced from `PROXMOX_VE_SSH_AUTH_SOCK`.
|
||||||
|
- `socks5_server` - (Optional) The address of the SOCKS5 proxy server to use for the SSH connection. Can also be sourced from `PROXMOX_VE_SSH_SOCKS5_SERVER`.
|
||||||
|
- `socks5_username` - (Optional) The username to use for the SOCKS5 proxy server. Can also be sourced from `PROXMOX_VE_SSH_SOCKS5_USERNAME`.
|
||||||
|
- `socks5_password` - (Optional) The password to use for the SOCKS5 proxy server. Can also be sourced from `PROXMOX_VE_SSH_SOCKS5_PASSWORD`.
|
||||||
- `node` - (Optional) The node configuration for the SSH connection. Can be specified multiple times to provide configuration fo multiple nodes.
|
- `node` - (Optional) The node configuration for the SSH connection. Can be specified multiple times to provide configuration fo multiple nodes.
|
||||||
- `name` - (Required) The name of the node.
|
- `name` - (Required) The name of the node.
|
||||||
- `address` - (Required) The FQDN/IP address of the node.
|
- `address` - (Required) The FQDN/IP address of the node.
|
||||||
|
@ -65,6 +65,9 @@ type proxmoxProviderModel struct {
|
|||||||
AgentSocket types.String `tfsdk:"agent_socket"`
|
AgentSocket types.String `tfsdk:"agent_socket"`
|
||||||
Password types.String `tfsdk:"password"`
|
Password types.String `tfsdk:"password"`
|
||||||
Username types.String `tfsdk:"username"`
|
Username types.String `tfsdk:"username"`
|
||||||
|
Socks5Server types.String `tfsdk:"socks5_server"`
|
||||||
|
Socks5Username types.String `tfsdk:"socks5_username"`
|
||||||
|
Socks5Password types.String `tfsdk:"socks5_password"`
|
||||||
|
|
||||||
Nodes []struct {
|
Nodes []struct {
|
||||||
Name types.String `tfsdk:"name"`
|
Name types.String `tfsdk:"name"`
|
||||||
@ -165,6 +168,22 @@ func (p *proxmoxProvider) Schema(_ context.Context, _ provider.SchemaRequest, re
|
|||||||
"`provider` block.",
|
"`provider` block.",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
|
"socks5_server": schema.StringAttribute{
|
||||||
|
Description: "The address:port of the SOCKS5 proxy server. " +
|
||||||
|
"Defaults to the value of the `PROXMOX_VE_SSH_SOCKS5_SERVER` environment variable.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"socks5_username": schema.StringAttribute{
|
||||||
|
Description: "The username for the SOCKS5 proxy server. " +
|
||||||
|
"Defaults to the value of the `PROXMOX_VE_SSH_SOCKS5_USERNAME` environment variable.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"socks5_password": schema.StringAttribute{
|
||||||
|
Description: "The password for the SOCKS5 proxy server. " +
|
||||||
|
"Defaults to the value of the `PROXMOX_VE_SSH_SOCKS5_PASSWORD` environment variable.",
|
||||||
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Blocks: map[string]schema.Block{
|
Blocks: map[string]schema.Block{
|
||||||
"node": schema.ListNestedBlock{
|
"node": schema.ListNestedBlock{
|
||||||
@ -314,6 +333,9 @@ func (p *proxmoxProvider) Configure(
|
|||||||
sshPassword := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PASSWORD")
|
sshPassword := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PASSWORD")
|
||||||
sshAgent := utils.GetAnyBoolEnv("PROXMOX_VE_SSH_AGENT")
|
sshAgent := utils.GetAnyBoolEnv("PROXMOX_VE_SSH_AGENT")
|
||||||
sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK")
|
sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK")
|
||||||
|
sshSocks5Server := utils.GetAnyStringEnv("PROXMOX_VE_SSH_SOCKS5_SERVER")
|
||||||
|
sshSocks5Username := utils.GetAnyStringEnv("PROXMOX_VE_SSH_SOCKS5_USERNAME")
|
||||||
|
sshSocks5Password := utils.GetAnyStringEnv("PROXMOX_VE_SSH_SOCKS5_PASSWORD")
|
||||||
nodeOverrides := map[string]ssh.ProxmoxNode{}
|
nodeOverrides := map[string]ssh.ProxmoxNode{}
|
||||||
|
|
||||||
//nolint: nestif
|
//nolint: nestif
|
||||||
@ -334,6 +356,18 @@ func (p *proxmoxProvider) Configure(
|
|||||||
sshAgentSocket = config.SSH[0].AgentSocket.ValueString()
|
sshAgentSocket = config.SSH[0].AgentSocket.ValueString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !config.SSH[0].Socks5Server.IsNull() {
|
||||||
|
sshSocks5Server = config.SSH[0].Socks5Server.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.SSH[0].Socks5Username.IsNull() {
|
||||||
|
sshSocks5Username = config.SSH[0].Socks5Username.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.SSH[0].Socks5Password.IsNull() {
|
||||||
|
sshSocks5Password = config.SSH[0].Socks5Password.ValueString()
|
||||||
|
}
|
||||||
|
|
||||||
for _, n := range config.SSH[0].Nodes {
|
for _, n := range config.SSH[0].Nodes {
|
||||||
nodePort := int32(n.Port.ValueInt64())
|
nodePort := int32(n.Port.ValueInt64())
|
||||||
if nodePort == 0 {
|
if nodePort == 0 {
|
||||||
@ -357,6 +391,7 @@ func (p *proxmoxProvider) Configure(
|
|||||||
|
|
||||||
sshClient, err := ssh.NewClient(
|
sshClient, err := ssh.NewClient(
|
||||||
sshUsername, sshPassword, sshAgent, sshAgentSocket,
|
sshUsername, sshPassword, sshAgent, sshAgentSocket,
|
||||||
|
sshSocks5Server, sshSocks5Username, sshSocks5Password,
|
||||||
&apiResolverWithOverrides{
|
&apiResolverWithOverrides{
|
||||||
ar: apiResolver{c: apiClient},
|
ar: apiResolver{c: apiClient},
|
||||||
overrides: nodeOverrides,
|
overrides: nodeOverrides,
|
||||||
|
@ -129,6 +129,7 @@ func uploadSnippetFile(t *testing.T, file *os.File) {
|
|||||||
|
|
||||||
sshClient, err := ssh.NewClient(
|
sshClient, err := ssh.NewClient(
|
||||||
sshUsername, "", true, sshAgentSocket,
|
sshUsername, "", true, sshAgentSocket,
|
||||||
|
"", "", "",
|
||||||
&nodeResolver{
|
&nodeResolver{
|
||||||
node: ssh.ProxmoxNode{
|
node: ssh.ProxmoxNode{
|
||||||
Address: u.Hostname(),
|
Address: u.Hostname(),
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/skeema/knownhosts"
|
"github.com/skeema/knownhosts"
|
||||||
"golang.org/x/crypto/ssh"
|
"golang.org/x/crypto/ssh"
|
||||||
"golang.org/x/crypto/ssh/agent"
|
"golang.org/x/crypto/ssh/agent"
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
"github.com/bpg/terraform-provider-proxmox/proxmox/api"
|
||||||
"github.com/bpg/terraform-provider-proxmox/utils"
|
"github.com/bpg/terraform-provider-proxmox/utils"
|
||||||
@ -45,6 +46,9 @@ type client struct {
|
|||||||
password string
|
password string
|
||||||
agent bool
|
agent bool
|
||||||
agentSocket string
|
agentSocket string
|
||||||
|
socks5Server string
|
||||||
|
socks5Username string
|
||||||
|
socks5Password string
|
||||||
nodeResolver NodeResolver
|
nodeResolver NodeResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +56,7 @@ type client struct {
|
|||||||
func NewClient(
|
func NewClient(
|
||||||
username string, password string,
|
username string, password string,
|
||||||
agent bool, agentSocket string,
|
agent bool, agentSocket string,
|
||||||
|
socks5Server string, socks5Username string, socks5Password string,
|
||||||
nodeResolver NodeResolver,
|
nodeResolver NodeResolver,
|
||||||
) (Client, error) {
|
) (Client, error) {
|
||||||
if agent && runtime.GOOS != "linux" && runtime.GOOS != "darwin" && runtime.GOOS != "freebsd" {
|
if agent && runtime.GOOS != "linux" && runtime.GOOS != "darwin" && runtime.GOOS != "freebsd" {
|
||||||
@ -61,6 +66,10 @@ func NewClient(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (socks5Username != "" || socks5Password != "") && socks5Server == "" {
|
||||||
|
return nil, errors.New("socks5 server is required when socks5 username or password is set")
|
||||||
|
}
|
||||||
|
|
||||||
if nodeResolver == nil {
|
if nodeResolver == nil {
|
||||||
return nil, errors.New("node resolver is required")
|
return nil, errors.New("node resolver is required")
|
||||||
}
|
}
|
||||||
@ -70,6 +79,9 @@ func NewClient(
|
|||||||
password: password,
|
password: password,
|
||||||
agent: agent,
|
agent: agent,
|
||||||
agentSocket: agentSocket,
|
agentSocket: agentSocket,
|
||||||
|
socks5Server: socks5Server,
|
||||||
|
socks5Username: socks5Username,
|
||||||
|
socks5Password: socks5Password,
|
||||||
nodeResolver: nodeResolver,
|
nodeResolver: nodeResolver,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -267,6 +279,41 @@ func (c *client) openNodeShell(ctx context.Context, node ProxmoxNode) (*ssh.Clie
|
|||||||
return kherr
|
return kherr
|
||||||
})
|
})
|
||||||
|
|
||||||
|
tflog.Info(ctx, fmt.Sprintf("agent is set to %t", c.agent))
|
||||||
|
|
||||||
|
var sshClient *ssh.Client
|
||||||
|
if c.agent {
|
||||||
|
sshClient, err = c.createSSHClientAgent(ctx, cb, kh, sshHost)
|
||||||
|
if err == nil {
|
||||||
|
return sshClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tflog.Error(ctx, "Failed ssh connection through agent, falling back to password authentication",
|
||||||
|
map[string]interface{}{
|
||||||
|
"error": err,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sshClient, err = c.createSSHClient(ctx, cb, kh, sshHost)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("unable to authenticate user %q over SSH to %q. Please verify that ssh-agent is "+
|
||||||
|
"correctly loaded with an authorized key via 'ssh-add -L' (NOTE: configurations in ~/.ssh/config are "+
|
||||||
|
"not considered by the provider): %w", c.username, sshHost, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sshClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) createSSHClient(
|
||||||
|
ctx context.Context,
|
||||||
|
cb ssh.HostKeyCallback,
|
||||||
|
kh knownhosts.HostKeyCallback,
|
||||||
|
sshHost string,
|
||||||
|
) (*ssh.Client, error) {
|
||||||
|
if c.password == "" {
|
||||||
|
tflog.Error(ctx, "Using password authentication fallback for SSH connection, but the SSH password is empty")
|
||||||
|
}
|
||||||
|
|
||||||
sshConfig := &ssh.ClientConfig{
|
sshConfig := &ssh.ClientConfig{
|
||||||
User: c.username,
|
User: c.username,
|
||||||
Auth: []ssh.AuthMethod{ssh.Password(c.password)},
|
Auth: []ssh.AuthMethod{ssh.Password(c.password)},
|
||||||
@ -274,39 +321,7 @@ func (c *client) openNodeShell(ctx context.Context, node ProxmoxNode) (*ssh.Clie
|
|||||||
HostKeyAlgorithms: kh.HostKeyAlgorithms(sshHost),
|
HostKeyAlgorithms: kh.HostKeyAlgorithms(sshHost),
|
||||||
}
|
}
|
||||||
|
|
||||||
tflog.Info(ctx, fmt.Sprintf("agent is set to %t", c.agent))
|
return c.connect(ctx, sshHost, sshConfig)
|
||||||
|
|
||||||
var sshClient *ssh.Client
|
|
||||||
if c.agent {
|
|
||||||
sshClient, err = c.createSSHClientAgent(ctx, cb, kh, sshHost)
|
|
||||||
if err != nil {
|
|
||||||
tflog.Error(ctx, "Failed ssh connection through agent, "+
|
|
||||||
"falling back to password authentication",
|
|
||||||
map[string]interface{}{
|
|
||||||
"error": err,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return sshClient, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sshClient, err = ssh.Dial("tcp", sshHost, sshConfig)
|
|
||||||
if err != nil {
|
|
||||||
if c.password == "" {
|
|
||||||
return nil, fmt.Errorf("unable to authenticate user %q over SSH to %q. Please verify that ssh-agent is "+
|
|
||||||
"correctly loaded with an authorized key via 'ssh-add -L' (NOTE: configurations in ~/.ssh/config are "+
|
|
||||||
"not considered by golang's ssh implementation). The exact error from ssh.Dial: %w", c.username, sshHost, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("failed to dial %s: %w", sshHost, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tflog.Debug(ctx, "SSH connection established", map[string]interface{}{
|
|
||||||
"host": sshHost,
|
|
||||||
"user": c.username,
|
|
||||||
})
|
|
||||||
|
|
||||||
return sshClient, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// createSSHClientAgent establishes an ssh connection through the agent authentication mechanism.
|
// createSSHClientAgent establishes an ssh connection through the agent authentication mechanism.
|
||||||
@ -335,6 +350,25 @@ func (c *client) createSSHClientAgent(
|
|||||||
HostKeyAlgorithms: kh.HostKeyAlgorithms(sshHost),
|
HostKeyAlgorithms: kh.HostKeyAlgorithms(sshHost),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return c.connect(ctx, sshHost, sshConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *client) connect(ctx context.Context, sshHost string, sshConfig *ssh.ClientConfig) (*ssh.Client, error) {
|
||||||
|
if c.socks5Server != "" {
|
||||||
|
sshClient, err := c.socks5SSHClient(sshHost, sshConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to dial %s via SOCKS5 proxy %s: %w", sshHost, c.socks5Server, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tflog.Debug(ctx, "SSH connection via SOCKS5 established", map[string]interface{}{
|
||||||
|
"host": sshHost,
|
||||||
|
"socks5_server": c.socks5Server,
|
||||||
|
"user": c.username,
|
||||||
|
})
|
||||||
|
|
||||||
|
return sshClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
sshClient, err := ssh.Dial("tcp", sshHost, sshConfig)
|
sshClient, err := ssh.Dial("tcp", sshHost, sshConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to dial %s: %w", sshHost, err)
|
return nil, fmt.Errorf("failed to dial %s: %w", sshHost, err)
|
||||||
@ -347,3 +381,25 @@ func (c *client) createSSHClientAgent(
|
|||||||
|
|
||||||
return sshClient, nil
|
return sshClient, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *client) socks5SSHClient(sshServerAddress string, sshConfig *ssh.ClientConfig) (*ssh.Client, error) {
|
||||||
|
dialer, err := proxy.SOCKS5("tcp", c.socks5Server, &proxy.Auth{
|
||||||
|
User: c.socks5Username,
|
||||||
|
Password: c.socks5Password,
|
||||||
|
}, proxy.Direct)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create SOCKS5 proxy dialer: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := dialer.Dial("tcp", sshServerAddress)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to dial %s via SOCKS5 proxy %s: %w", sshServerAddress, c.socks5Server, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
sshConn, chans, reqs, err := ssh.NewClientConn(conn, sshServerAddress, sshConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to create SSH client connection: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ssh.NewClient(sshConn, chans, reqs), nil
|
||||||
|
}
|
||||||
|
@ -111,6 +111,9 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
|
|||||||
sshPassword := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PASSWORD", "PM_VE_SSH_PASSWORD")
|
sshPassword := utils.GetAnyStringEnv("PROXMOX_VE_SSH_PASSWORD", "PM_VE_SSH_PASSWORD")
|
||||||
sshAgent := utils.GetAnyBoolEnv("PROXMOX_VE_SSH_AGENT", "PM_VE_SSH_AGENT")
|
sshAgent := utils.GetAnyBoolEnv("PROXMOX_VE_SSH_AGENT", "PM_VE_SSH_AGENT")
|
||||||
sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK", "PM_VE_SSH_AUTH_SOCK")
|
sshAgentSocket := utils.GetAnyStringEnv("SSH_AUTH_SOCK", "PROXMOX_VE_SSH_AUTH_SOCK", "PM_VE_SSH_AUTH_SOCK")
|
||||||
|
sshSocks5Server := utils.GetAnyStringEnv("PROXMOX_VE_SSH_SOCKS5_SERVER")
|
||||||
|
sshSocks5Username := utils.GetAnyStringEnv("PROXMOX_VE_SSH_SOCKS5_USERNAME")
|
||||||
|
sshSocks5Password := utils.GetAnyStringEnv("PROXMOX_VE_SSH_SOCKS5_PASSWORD")
|
||||||
|
|
||||||
if v, ok := sshConf[mkProviderSSHUsername]; !ok || v.(string) == "" {
|
if v, ok := sshConf[mkProviderSSHUsername]; !ok || v.(string) == "" {
|
||||||
if sshUsername != "" {
|
if sshUsername != "" {
|
||||||
@ -136,6 +139,18 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
|
|||||||
sshConf[mkProviderSSHAgentSocket] = sshAgentSocket
|
sshConf[mkProviderSSHAgentSocket] = sshAgentSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if _, ok := sshConf[mkProviderSSHSocks5Server]; !ok {
|
||||||
|
sshConf[mkProviderSSHSocks5Server] = sshSocks5Server
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := sshConf[mkProviderSSHSocks5Username]; !ok {
|
||||||
|
sshConf[mkProviderSSHSocks5Username] = sshSocks5Username
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := sshConf[mkProviderSSHSocks5Password]; !ok {
|
||||||
|
sshConf[mkProviderSSHSocks5Password] = sshSocks5Password
|
||||||
|
}
|
||||||
|
|
||||||
nodeOverrides := map[string]ssh.ProxmoxNode{}
|
nodeOverrides := map[string]ssh.ProxmoxNode{}
|
||||||
|
|
||||||
if ns, ok := sshConf[mkProviderSSHNode]; ok {
|
if ns, ok := sshConf[mkProviderSSHNode]; ok {
|
||||||
@ -153,6 +168,9 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
|
|||||||
sshConf[mkProviderSSHPassword].(string),
|
sshConf[mkProviderSSHPassword].(string),
|
||||||
sshConf[mkProviderSSHAgent].(bool),
|
sshConf[mkProviderSSHAgent].(bool),
|
||||||
sshConf[mkProviderSSHAgentSocket].(string),
|
sshConf[mkProviderSSHAgentSocket].(string),
|
||||||
|
sshConf[mkProviderSSHSocks5Server].(string),
|
||||||
|
sshConf[mkProviderSSHSocks5Username].(string),
|
||||||
|
sshConf[mkProviderSSHSocks5Password].(string),
|
||||||
&apiResolverWithOverrides{
|
&apiResolverWithOverrides{
|
||||||
ar: apiResolver{c: apiClient},
|
ar: apiResolver{c: apiClient},
|
||||||
overrides: nodeOverrides,
|
overrides: nodeOverrides,
|
||||||
|
@ -29,6 +29,9 @@ const (
|
|||||||
mkProviderSSHPassword = "password"
|
mkProviderSSHPassword = "password"
|
||||||
mkProviderSSHAgent = "agent"
|
mkProviderSSHAgent = "agent"
|
||||||
mkProviderSSHAgentSocket = "agent_socket"
|
mkProviderSSHAgentSocket = "agent_socket"
|
||||||
|
mkProviderSSHSocks5Server = "socks5_server"
|
||||||
|
mkProviderSSHSocks5Username = "socks5_username"
|
||||||
|
mkProviderSSHSocks5Password = "socks5_password"
|
||||||
|
|
||||||
mkProviderSSHNode = "node"
|
mkProviderSSHNode = "node"
|
||||||
mkProviderSSHNodeName = "name"
|
mkProviderSSHNodeName = "name"
|
||||||
@ -145,6 +148,40 @@ func createSchema() map[string]*schema.Schema {
|
|||||||
),
|
),
|
||||||
ValidateFunc: validation.StringIsNotEmpty,
|
ValidateFunc: validation.StringIsNotEmpty,
|
||||||
},
|
},
|
||||||
|
mkProviderSSHSocks5Server: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "The address:port of the SOCKS5 proxy server. " +
|
||||||
|
"Defaults to the value of the `PROXMOX_VE_SSH_SOCKS5_SERVER` environment variable.",
|
||||||
|
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||||
|
[]string{"PROXMOX_VE_SSH_SOCKS5_SERVER"},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
ValidateFunc: validation.StringIsNotEmpty,
|
||||||
|
},
|
||||||
|
mkProviderSSHSocks5Username: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: "The username for the SOCKS5 proxy server. " +
|
||||||
|
"Defaults to the value of the `PROXMOX_VE_SSH_SOCKS5_USERNAME` environment variable.",
|
||||||
|
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||||
|
[]string{"PROXMOX_VE_SSH_SOCKS5_USERNAME"},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
ValidateFunc: validation.StringIsNotEmpty,
|
||||||
|
},
|
||||||
|
mkProviderSSHSocks5Password: {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
|
Description: "The password for the SOCKS5 proxy server. " +
|
||||||
|
"Defaults to the value of the `PROXMOX_VE_SSH_SOCKS5_PASSWORD` environment variable.",
|
||||||
|
DefaultFunc: schema.MultiEnvDefaultFunc(
|
||||||
|
[]string{"PROXMOX_VE_SSH_SOCKS5_PASSWORD"},
|
||||||
|
nil,
|
||||||
|
),
|
||||||
|
ValidateFunc: validation.StringIsNotEmpty,
|
||||||
|
},
|
||||||
mkProviderSSHNode: {
|
mkProviderSSHNode: {
|
||||||
Type: schema.TypeList,
|
Type: schema.TypeList,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user