0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-08-24 12:28:34 +00:00

feat: add min-tls option to provider config (#931)

* feat: add min-tls option to provider config

Signed-off-by: Robert Kaussow <mail@thegeeklab.de>

* fix: clenup code and add min-tls to file resource

Signed-off-by: Robert Kaussow <mail@thegeeklab.de>

* fix: linter errors, wrong schema type in file resource

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>

* chore: update docs

Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>

---------

Signed-off-by: Robert Kaussow <mail@thegeeklab.de>
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
Co-authored-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
Robert Kaussow 2024-01-20 02:26:14 +01:00 committed by GitHub
parent 7d94bf73ec
commit 01ff2cb7db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 82 additions and 10 deletions

View File

@ -21,7 +21,7 @@ provider "proxmox" {
password = "the-password-set-during-installation-of-proxmox-ve"
# because self-signed TLS certificate is in use
insecure = true
# uncoment (unless on Windows...)
# uncomment (unless on Windows...)
# tmp_dir = "/var/tmp"
ssh {
@ -222,6 +222,7 @@ In addition to [generic provider arguments](https://www.terraform.io/docs/config
- `endpoint` - (Required) The endpoint for the Proxmox Virtual Environment API (can also be sourced from `PROXMOX_VE_ENDPOINT`). Usually this is `https://<your-cluster-endpoint>:8006/`. **Do not** include `/api2/json` at the end.
- `insecure` - (Optional) Whether to skip the TLS verification step (can also be sourced from `PROXMOX_VE_INSECURE`). If omitted, defaults to `false`.
- `min_tls` - (Optional) The minimum required TLS version for API calls (can also be sourced from `PROXMOX_VE_MIN_TLS`). Supported values: `1.0|1.1|1.2|1.3`. If omitted, defaults to `1.3`.
- `otp` - (Optional, Deprecated) The one-time password for the Proxmox Virtual Environment API (can also be sourced from `PROXMOX_VE_OTP`).
- `password` - (Required) The password for the Proxmox Virtual Environment API (can also be sourced from `PROXMOX_VE_PASSWORD`).
- `username` - (Required) The username and realm for the Proxmox Virtual Environment API (can also be sourced from `PROXMOX_VE_USERNAME`). For example, `root@pam`.

View File

@ -117,6 +117,7 @@ resource "proxmox_virtual_environment_file" "ubuntu_container_template" {
when the source file is a URL referencing a `.qcow2` image.
- `insecure` - (Optional) Whether to skip the TLS verification step for
HTTPS sources (defaults to `false`).
- `min_tls` - (Optional) The minimum required TLS version for HTTPS sources. "Supported values: `1.0|1.1|1.2|1.3` (defaults to `1.3`).
- `path` - (Required) A path to a local file or a URL.
- `source_raw` - (Optional) The raw source (conflicts with `source_file`).
- `data` - (Required) The raw data.

View File

@ -56,6 +56,7 @@ type proxmoxProviderModel struct {
APIToken types.String `tfsdk:"api_token"`
Endpoint types.String `tfsdk:"endpoint"`
Insecure types.Bool `tfsdk:"insecure"`
MinTLS types.String `tfsdk:"min_tls"`
OTP types.String `tfsdk:"otp"`
Username types.String `tfsdk:"username"`
Password types.String `tfsdk:"password"`
@ -106,6 +107,11 @@ func (p *proxmoxProvider) Schema(_ context.Context, _ provider.SchemaRequest, re
Description: "Whether to skip the TLS verification step.",
Optional: true,
},
"min_tls": schema.StringAttribute{
Description: "The minimum required TLS version for API calls." +
"Supported values: `1.0|1.1|1.2|1.3`. Defaults to `1.3`.",
Optional: true,
},
"otp": schema.StringAttribute{
Description: "The one-time password for the Proxmox VE API.",
Optional: true,
@ -228,6 +234,7 @@ func (p *proxmoxProvider) Configure(
apiToken := utils.GetAnyStringEnv("PROXMOX_VE_API_TOKEN")
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT")
insecure := utils.GetAnyBoolEnv("PROXMOX_VE_INSECURE")
minTLS := utils.GetAnyStringEnv("PROXMOX_VE_MIN_TLS")
username := utils.GetAnyStringEnv("PROXMOX_VE_USERNAME")
password := utils.GetAnyStringEnv("PROXMOX_VE_PASSWORD")
@ -243,6 +250,10 @@ func (p *proxmoxProvider) Configure(
insecure = config.Insecure.ValueBool()
}
if !config.MinTLS.IsNull() {
minTLS = config.MinTLS.ValueString()
}
if !config.Username.IsNull() {
username = config.Username.ValueString()
}
@ -278,6 +289,7 @@ func (p *proxmoxProvider) Configure(
conn, err := api.NewConnection(
endpoint,
insecure,
minTLS,
)
if err != nil {
resp.Diagnostics.AddError(

View File

@ -92,7 +92,7 @@ func getNodesClient() *nodes.Client {
panic(err)
}
conn, err := api.NewConnection(endpoint, true)
conn, err := api.NewConnection(endpoint, true, "")
if err != nil {
panic(err)
}

View File

@ -16,11 +16,13 @@ import (
"io"
"net/http"
"net/url"
"sort"
"strings"
"github.com/google/go-querystring/query"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging"
"golang.org/x/exp/maps"
"github.com/bpg/terraform-provider-proxmox/utils"
)
@ -59,7 +61,7 @@ type Connection struct {
}
// NewConnection creates and initializes a Connection instance.
func NewConnection(endpoint string, insecure bool) (*Connection, error) {
func NewConnection(endpoint string, insecure bool, minTLS string) (*Connection, error) {
u, err := url.ParseRequestURI(endpoint)
if err != nil {
return nil, errors.New(
@ -73,10 +75,15 @@ func NewConnection(endpoint string, insecure bool) (*Connection, error) {
)
}
version, err := GetMinTLSVersion(minTLS)
if err != nil {
return nil, err
}
var transport http.RoundTripper = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS13,
MinVersion: version,
InsecureSkipVerify: insecure, //nolint:gosec
},
}
@ -317,3 +324,24 @@ func validateResponseCode(res *http.Response) error {
return nil
}
// GetMinTLSVersion returns the minimum TLS version constant for the given string. If the string is empty,
// the default TLS version is returned. For unsupported TLS versions, an error is returned.
func GetMinTLSVersion(version string) (uint16, error) {
validVersions := map[string]uint16{
"": tls.VersionTLS13,
"1.3": tls.VersionTLS13,
"1.2": tls.VersionTLS12,
"1.1": tls.VersionTLS11,
"1.0": tls.VersionTLS10,
}
if val, ok := validVersions[strings.TrimSpace(version)]; ok {
return val, nil
}
valid := maps.Keys(validVersions)
sort.Strings(valid)
return 0, fmt.Errorf("unsupported minimal TLS version %s, must be one of: %s", version, strings.Join(valid, ", "))
}

View File

@ -50,6 +50,7 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
apiToken := utils.GetAnyStringEnv("PROXMOX_VE_API_TOKEN", "PM_VE_API_TOKEN")
endpoint := utils.GetAnyStringEnv("PROXMOX_VE_ENDPOINT", "PM_VE_ENDPOINT")
insecure := utils.GetAnyBoolEnv("PROXMOX_VE_INSECURE", "PM_VE_INSECURE")
minTLS := utils.GetAnyStringEnv("PROXMOX_VE_MIN_TLS", "PM_VE_MIN_TLS")
username := utils.GetAnyStringEnv("PROXMOX_VE_USERNAME", "PM_VE_USERNAME")
password := utils.GetAnyStringEnv("PROXMOX_VE_PASSWORD", "PM_VE_PASSWORD")
otp := utils.GetAnyStringEnv("PROXMOX_VE_OTP", "PM_VE_OTP")
@ -66,6 +67,10 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
insecure = v.(bool)
}
if v, ok := d.GetOk(mkProviderMinTLS); ok {
minTLS = v.(string)
}
if v, ok := d.GetOk(mkProviderUsername); ok {
username = v.(string)
}
@ -81,7 +86,7 @@ func providerConfigure(_ context.Context, d *schema.ResourceData) (interface{},
creds, err = api.NewCredentials(username, password, otp, apiToken)
diags = append(diags, diag.FromErr(err)...)
conn, err = api.NewConnection(endpoint, insecure)
conn, err = api.NewConnection(endpoint, insecure, minTLS)
diags = append(diags, diag.FromErr(err)...)
if diags.HasError() {

View File

@ -37,6 +37,7 @@ func TestProviderSchema(t *testing.T) {
mkProviderPassword,
mkProviderEndpoint,
mkProviderInsecure,
mkProviderMinTLS,
mkProviderOTP,
})
@ -45,6 +46,7 @@ func TestProviderSchema(t *testing.T) {
mkProviderPassword: schema.TypeString,
mkProviderEndpoint: schema.TypeString,
mkProviderInsecure: schema.TypeBool,
mkProviderMinTLS: schema.TypeString,
mkProviderOTP: schema.TypeString,
})

View File

@ -18,6 +18,7 @@ const (
dvProviderOTP = ""
mkProviderEndpoint = "endpoint"
mkProviderInsecure = "insecure"
mkProviderMinTLS = "min_tls"
mkProviderOTP = "otp"
mkProviderPassword = "password"
mkProviderUsername = "username"
@ -48,6 +49,12 @@ func createSchema() map[string]*schema.Schema {
Optional: true,
Description: "Whether to skip the TLS verification step.",
},
mkProviderMinTLS: {
Type: schema.TypeString,
Optional: true,
Description: "The minimum required TLS version for API calls." +
"Supported values: `1.0|1.1|1.2|1.3`. Defaults to `1.3`.",
},
mkProviderOTP: {
Type: schema.TypeString,
Optional: true,

View File

@ -39,6 +39,7 @@ const (
dvResourceVirtualEnvironmentFileSourceFileChecksum = ""
dvResourceVirtualEnvironmentFileSourceFileFileName = ""
dvResourceVirtualEnvironmentFileSourceFileInsecure = false
dvResourceVirtualEnvironmentFileSourceFileMinTLS = ""
dvResourceVirtualEnvironmentFileOverwrite = true
dvResourceVirtualEnvironmentFileSourceRawResize = 0
dvResourceVirtualEnvironmentFileTimeoutUpload = 1800
@ -57,6 +58,7 @@ const (
mkResourceVirtualEnvironmentFileSourceFileChecksum = "checksum"
mkResourceVirtualEnvironmentFileSourceFileFileName = "file_name"
mkResourceVirtualEnvironmentFileSourceFileInsecure = "insecure"
mkResourceVirtualEnvironmentFileSourceFileMinTLS = "min_tls"
mkResourceVirtualEnvironmentFileSourceRaw = "source_raw"
mkResourceVirtualEnvironmentFileSourceRawData = "data"
mkResourceVirtualEnvironmentFileSourceRawFileName = "file_name"
@ -155,6 +157,14 @@ func File() *schema.Resource {
ForceNew: true,
Default: dvResourceVirtualEnvironmentFileSourceFileInsecure,
},
mkResourceVirtualEnvironmentFileSourceFileMinTLS: {
Type: schema.TypeString,
Description: "The minimum required TLS version for HTTPS sources." +
"Supported values: `1.0|1.1|1.2|1.3`. Defaults to `1.3`.",
Optional: true,
ForceNew: true,
Default: dvResourceVirtualEnvironmentFileSourceFileMinTLS,
},
},
},
MaxItems: 1,
@ -372,6 +382,7 @@ func fileCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag
sourceFileBlock := sourceFile[0].(map[string]interface{})
sourceFilePath := sourceFileBlock[mkResourceVirtualEnvironmentFileSourceFilePath].(string)
sourceFileChecksum := sourceFileBlock[mkResourceVirtualEnvironmentFileSourceFileChecksum].(string)
sourceFileMinTLS := sourceFileBlock[mkResourceVirtualEnvironmentFileSourceFileMinTLS].(string)
sourceFileInsecure := sourceFileBlock[mkResourceVirtualEnvironmentFileSourceFileInsecure].(bool)
if fileIsURL(d) {
@ -379,10 +390,15 @@ func fileCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag
"url": sourceFilePath,
})
version, e := api.GetMinTLSVersion(sourceFileMinTLS)
if e != nil {
return diag.FromErr(e)
}
httpClient := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
MinVersion: tls.VersionTLS13,
MinVersion: version,
InsecureSkipVerify: sourceFileInsecure,
},
},