Skip to content

Commit 886416c

Browse files
authored
Merge pull request #85 from arnaud-dfns/feat/ssh-key-password
2 parents 747d6aa + 171e0d6 commit 886416c

File tree

5 files changed

+104
-34
lines changed

5 files changed

+104
-34
lines changed

docs/data-sources/ssh.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ provider "kubernetes" {
4444

4545
### Optional
4646

47+
- `ssh_key` (String, Sensitive) The path to the private key file or the private key content to use for the SSH connection
48+
- `ssh_key_passphrase` (String, Sensitive) The passphrase for the private key file
49+
- `ssh_password` (String, Sensitive) The password to use for the SSH connection
4750
- `ssh_port` (Number) The port number of the SSH bastion host
4851
- `ssh_user` (String) The username to use for the SSH connection
4952

docs/ephemeral-resources/ssh.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ provider "kubernetes" {
4444

4545
### Optional
4646

47+
- `ssh_key` (String, Sensitive) The path to the private key file or the private key content to use for the SSH connection
48+
- `ssh_key_passphrase` (String, Sensitive) The passphrase for the private key file
49+
- `ssh_password` (String, Sensitive) The password to use for the SSH connection
4750
- `ssh_port` (Number) The port number of the SSH bastion host
4851
- `ssh_user` (String) The username to use for the SSH connection
4952

internal/provider/data_source_ssh.go

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,16 @@ type SSHDataSource struct{}
2424

2525
// SSHDataSourceModel describes the data source data model.
2626
type SSHDataSourceModel struct {
27-
LocalHost types.String `tfsdk:"local_host"`
28-
LocalPort types.Int64 `tfsdk:"local_port"`
29-
SSHHost types.String `tfsdk:"ssh_host"`
30-
SSHPort types.Int64 `tfsdk:"ssh_port"`
31-
SSHUser types.String `tfsdk:"ssh_user"`
32-
TargetHost types.String `tfsdk:"target_host"`
33-
TargetPort types.Int64 `tfsdk:"target_port"`
27+
LocalHost types.String `tfsdk:"local_host"`
28+
LocalPort types.Int64 `tfsdk:"local_port"`
29+
SSHHost types.String `tfsdk:"ssh_host"`
30+
SSHKey types.String `tfsdk:"ssh_key"`
31+
SSHKeyPassphrase types.String `tfsdk:"ssh_key_passphrase"`
32+
SSHPassword types.String `tfsdk:"ssh_password"`
33+
SSHPort types.Int64 `tfsdk:"ssh_port"`
34+
SSHUser types.String `tfsdk:"ssh_user"`
35+
TargetHost types.String `tfsdk:"target_host"`
36+
TargetPort types.Int64 `tfsdk:"target_port"`
3437
}
3538

3639
func (d *SSHDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
@@ -65,7 +68,21 @@ func (d *SSHDataSource) Schema(ctx context.Context, req datasource.SchemaRequest
6568
Optional: true,
6669
Computed: true,
6770
},
68-
71+
"ssh_password": schema.StringAttribute{
72+
MarkdownDescription: "The password to use for the SSH connection",
73+
Optional: true,
74+
Sensitive: true,
75+
},
76+
"ssh_key": schema.StringAttribute{
77+
MarkdownDescription: "The path to the private key file or the private key content to use for the SSH connection",
78+
Optional: true,
79+
Sensitive: true,
80+
},
81+
"ssh_key_passphrase": schema.StringAttribute{
82+
MarkdownDescription: "The passphrase for the private key file",
83+
Optional: true,
84+
Sensitive: true,
85+
},
6986
// Computed attributes
7087
"local_host": schema.StringAttribute{
7188
MarkdownDescription: "The DNS name or IP address of the local host",
@@ -112,12 +129,15 @@ func (d *SSHDataSource) Read(ctx context.Context, req datasource.ReadRequest, re
112129
}
113130

114131
_, err = ssh.ForkRemoteTunnel(ctx, ssh.TunnelConfig{
115-
LocalPort: localPort,
116-
SSHHost: data.SSHHost.ValueString(),
117-
SSHPort: int(data.SSHPort.ValueInt64()),
118-
SSHUser: data.SSHUser.ValueString(),
119-
TargetHost: data.TargetHost.ValueString(),
120-
TargetPort: int(data.TargetPort.ValueInt64()),
132+
LocalPort: localPort,
133+
SSHHost: data.SSHHost.ValueString(),
134+
SSHKey: data.SSHKey.ValueString(),
135+
SSHKeyPassphrase: data.SSHKeyPassphrase.ValueString(),
136+
SSHPassword: data.SSHPassword.ValueString(),
137+
SSHPort: int(data.SSHPort.ValueInt64()),
138+
SSHUser: data.SSHUser.ValueString(),
139+
TargetHost: data.TargetHost.ValueString(),
140+
TargetPort: int(data.TargetPort.ValueInt64()),
121141
})
122142
if err != nil {
123143
resp.Diagnostics.AddError("Failed to fork tunnel process", fmt.Sprintf("Error: %s", err))

internal/provider/ephemeral_ssh.go

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ type SSHEphemeral struct{}
2525

2626
// SSHEphemeralModel describes the data source data model.
2727
type SSHEphemeralModel struct {
28-
LocalHost types.String `tfsdk:"local_host"`
29-
LocalPort types.Int64 `tfsdk:"local_port"`
30-
SSHHost types.String `tfsdk:"ssh_host"`
31-
SSHPort types.Int64 `tfsdk:"ssh_port"`
32-
SSHUser types.String `tfsdk:"ssh_user"`
33-
TargetHost types.String `tfsdk:"target_host"`
34-
TargetPort types.Int64 `tfsdk:"target_port"`
28+
LocalHost types.String `tfsdk:"local_host"`
29+
LocalPort types.Int64 `tfsdk:"local_port"`
30+
SSHHost types.String `tfsdk:"ssh_host"`
31+
SSHKey types.String `tfsdk:"ssh_key"`
32+
SSHKeyPassphrase types.String `tfsdk:"ssh_key_passphrase"`
33+
SSHPassword types.String `tfsdk:"ssh_password"`
34+
SSHPort types.Int64 `tfsdk:"ssh_port"`
35+
SSHUser types.String `tfsdk:"ssh_user"`
36+
TargetHost types.String `tfsdk:"target_host"`
37+
TargetPort types.Int64 `tfsdk:"target_port"`
3538
}
3639

3740
func (d *SSHEphemeral) Metadata(ctx context.Context, req ephemeral.MetadataRequest, resp *ephemeral.MetadataResponse) {
@@ -66,7 +69,21 @@ func (d *SSHEphemeral) Schema(ctx context.Context, req ephemeral.SchemaRequest,
6669
Optional: true,
6770
Computed: true,
6871
},
69-
72+
"ssh_password": schema.StringAttribute{
73+
MarkdownDescription: "The password to use for the SSH connection",
74+
Optional: true,
75+
Sensitive: true,
76+
},
77+
"ssh_key": schema.StringAttribute{
78+
MarkdownDescription: "The path to the private key file or the private key content to use for the SSH connection",
79+
Optional: true,
80+
Sensitive: true,
81+
},
82+
"ssh_key_passphrase": schema.StringAttribute{
83+
MarkdownDescription: "The passphrase for the private key file",
84+
Optional: true,
85+
Sensitive: true,
86+
},
7087
// Computed attributes
7188
"local_host": schema.StringAttribute{
7289
MarkdownDescription: "The DNS name or IP address of the local host",
@@ -113,12 +130,15 @@ func (d *SSHEphemeral) Open(ctx context.Context, req ephemeral.OpenRequest, resp
113130
}
114131

115132
cmd, err := ssh.ForkRemoteTunnel(ctx, ssh.TunnelConfig{
116-
LocalPort: localPort,
117-
SSHHost: data.SSHHost.ValueString(),
118-
SSHPort: int(data.SSHPort.ValueInt64()),
119-
SSHUser: data.SSHUser.ValueString(),
120-
TargetHost: data.TargetHost.ValueString(),
121-
TargetPort: int(data.TargetPort.ValueInt64()),
133+
LocalPort: localPort,
134+
SSHHost: data.SSHHost.ValueString(),
135+
SSHKey: data.SSHKey.ValueString(),
136+
SSHKeyPassphrase: data.SSHKeyPassphrase.ValueString(),
137+
SSHPassword: data.SSHPassword.ValueString(),
138+
SSHPort: int(data.SSHPort.ValueInt64()),
139+
SSHUser: data.SSHUser.ValueString(),
140+
TargetHost: data.TargetHost.ValueString(),
141+
TargetPort: int(data.TargetPort.ValueInt64()),
122142
})
123143
if err != nil {
124144
resp.Diagnostics.AddError("Failed to fork tunnel process", fmt.Sprintf("Error: %s", err))

internal/ssh/tunnel.go

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"os/signal"
1313
"path/filepath"
1414
"strconv"
15+
"strings"
1516
"time"
1617

1718
"github.com/dfns/terraform-provider-tunnel/internal/libs"
@@ -21,12 +22,15 @@ import (
2122
var TunnelType string = "ssh"
2223

2324
type TunnelConfig struct {
24-
SSHHost string
25-
SSHPort int
26-
SSHUser string
27-
TargetHost string
28-
TargetPort int
29-
LocalPort int
25+
LocalPort int
26+
SSHHost string
27+
SSHKey string
28+
SSHKeyPassphrase string
29+
SSHPassword string
30+
SSHPort int
31+
SSHUser string
32+
TargetHost string
33+
TargetPort int
3034
}
3135

3236
func ForkRemoteTunnel(ctx context.Context, cfg TunnelConfig) (*exec.Cmd, error) {
@@ -89,6 +93,26 @@ func StartRemoteTunnel(ctx context.Context, cfgJson string, parentPid int) (err
8993
sshTun.SetUser(cfg.SSHUser)
9094
sshTun.SetRemoteHost(cfg.TargetHost)
9195

96+
if cfg.SSHPassword != "" {
97+
sshTun.SetPassword(cfg.SSHPassword)
98+
}
99+
100+
if cfg.SSHKey != "" {
101+
if _, err := os.Stat(cfg.SSHKey); err == nil {
102+
if cfg.SSHKeyPassphrase != "" {
103+
sshTun.SetEncryptedKeyFile(cfg.SSHKey, cfg.SSHKeyPassphrase)
104+
} else {
105+
sshTun.SetKeyFile(cfg.SSHKey)
106+
}
107+
} else {
108+
if cfg.SSHKeyPassphrase != "" {
109+
sshTun.SetEncryptedKeyReader(strings.NewReader(cfg.SSHKey), cfg.SSHKeyPassphrase)
110+
} else {
111+
sshTun.SetKeyReader(strings.NewReader(cfg.SSHKey))
112+
}
113+
}
114+
}
115+
92116
sshTun.SetTunneledConnState(func(tun *sshtun.SSHTun, state *sshtun.TunneledConnState) {
93117
log.Printf("tunnel state: %+v", state)
94118
})

0 commit comments

Comments
 (0)