From d596852f8c41fd7811fbaeb52390a5a6f4895b9a Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 2 Aug 2019 14:01:52 +0200 Subject: [PATCH] Use OTP 2FA --- README.md | 8 +++++++- examples/cloudinit_example.tf | 1 + examples/lxc_example.tf | 1 + proxmox/provider.go | 12 +++++++++--- proxmox/provisioner.go | 2 +- proxmox/resource_vm_qemu.go | 1 + 6 files changed, 20 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 83b56bb..b30e058 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,11 @@ export PM_API_URL="https://xxxx.com:8006/api2/json" export PM_USER=user@pam export PM_PASS=password ``` - +If a 2FA OTP code is required +```bash +# Optional 2FA OTP code +export PM_OTP=otpcode +``` ## Run @@ -58,6 +62,8 @@ provider "proxmox" { pm_api_url = "https://proxmox-server01.example.com:8006/api2/json" pm_password = "secret" pm_user = "terraform-user@pve" + //Optional + pm_otp = "otpcode" */ } diff --git a/examples/cloudinit_example.tf b/examples/cloudinit_example.tf index 32f4e3b..4d5b92a 100644 --- a/examples/cloudinit_example.tf +++ b/examples/cloudinit_example.tf @@ -3,6 +3,7 @@ provider "proxmox" { pm_api_url = "https://proxmox-server01.example.com:8006/api2/json" pm_password = "secret" pm_user = "terraform-user@pve" + pm_otp = "" } resource "proxmox_vm_qemu" "cloudinit-test" { diff --git a/examples/lxc_example.tf b/examples/lxc_example.tf index 4829f18..199a21f 100644 --- a/examples/lxc_example.tf +++ b/examples/lxc_example.tf @@ -3,6 +3,7 @@ provider "proxmox" { pm_api_url = "https://proxmox.org/api2/json" pm_password = "supersecret" pm_user = "terraform-user@pve" + pm_otp = "" } resource "proxmox_lxc" "lxc-test" { diff --git a/proxmox/provider.go b/proxmox/provider.go index c829ddc..8b9f52b 100644 --- a/proxmox/provider.go +++ b/proxmox/provider.go @@ -54,6 +54,12 @@ func Provider() *schema.Provider { Optional: true, Default: false, }, + "pm_otp": { + Type: schema.TypeString, + Required: true, + DefaultFunc: schema.EnvDefaultFunc("PM_OTP", nil), + Description: "OTP 2FA code (if required)", + }, }, ResourcesMap: map[string]*schema.Resource{ @@ -69,7 +75,7 @@ func Provider() *schema.Provider { } func providerConfigure(d *schema.ResourceData) (interface{}, error) { - client, err := getClient(d.Get("pm_api_url").(string), d.Get("pm_user").(string), d.Get("pm_password").(string), d.Get("pm_tls_insecure").(bool)) + client, err := getClient(d.Get("pm_api_url").(string), d.Get("pm_user").(string), d.Get("pm_password").(string), d.Get("pm_otp").(string), d.Get("pm_tls_insecure").(bool)) if err != nil { return nil, err } @@ -84,13 +90,13 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { }, nil } -func getClient(pm_api_url string, pm_user string, pm_password string, pm_tls_insecure bool) (*pxapi.Client, error) { +func getClient(pm_api_url string, pm_user string, pm_password string, pm_otp string, pm_tls_insecure bool) (*pxapi.Client, error) { tlsconf := &tls.Config{InsecureSkipVerify: true} if !pm_tls_insecure { tlsconf = nil } client, _ := pxapi.NewClient(pm_api_url, nil, tlsconf) - err := client.Login(pm_user, pm_password) + err := client.Login(pm_user, pm_password, pm_otp) if err != nil { return nil, err } diff --git a/proxmox/provisioner.go b/proxmox/provisioner.go index b27c3d3..8fc41a8 100644 --- a/proxmox/provisioner.go +++ b/proxmox/provisioner.go @@ -45,7 +45,7 @@ func applyFn(ctx context.Context) error { vmr.SetNode(targetNode) client := currentClient if client == nil { - client, err = getClient(connInfo["pm_api_url"], connInfo["pm_user"], connInfo["pm_password"], connInfo["pm_tls_insecure"] == "true") + client, err = getClient(connInfo["pm_api_url"], connInfo["pm_user"], connInfo["pm_password"], connInfo["pm_otp"], connInfo["pm_tls_insecure"] == "true") if err != nil { return err } diff --git a/proxmox/resource_vm_qemu.go b/proxmox/resource_vm_qemu.go index 5fa93a2..55b214d 100644 --- a/proxmox/resource_vm_qemu.go +++ b/proxmox/resource_vm_qemu.go @@ -839,6 +839,7 @@ func initConnInfo( "pm_api_url": client.ApiUrl, "pm_user": client.Username, "pm_password": client.Password, + "pm_otp": client.Otp, "pm_tls_insecure": "true", // TODO - pass pm_tls_insecure state around, but if we made it this far, default insecure }) return nil