0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-07-01 02:52:58 +00:00
terraform-provider-proxmox/proxmoxtf/resource_virtual_environment_certificate.go
Pavel Boldyrev bf9e31ecfc
chore: lint and reformat the code (#204)
* chore: reformat code

* chore: add commitlint config

* reformat README.md

* add linter config

* lint & reformat docs

* go linter: only new issues

* fix some linting errors

* more reformatting

* disable linter warning for some duplicated code
2023-01-16 18:07:30 -05:00

360 lines
11 KiB
Go

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package proxmoxtf
import (
"context"
"fmt"
"strings"
"time"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/bpg/terraform-provider-proxmox/proxmox"
)
const (
dvResourceVirtualEnvironmentCertificateCertificateChain = ""
dvResourceVirtualEnvironmentCertificateOverwrite = false
mkResourceVirtualEnvironmentCertificateCertificate = "certificate"
mkResourceVirtualEnvironmentCertificateCertificateChain = "certificate_chain"
mkResourceVirtualEnvironmentCertificateFileName = "file_name"
mkResourceVirtualEnvironmentCertificateIssuer = "issuer"
mkResourceVirtualEnvironmentCertificateNodeName = "node_name"
mkResourceVirtualEnvironmentCertificateExpirationDate = "expiration_date"
mkResourceVirtualEnvironmentCertificateOverwrite = "overwrite"
mkResourceVirtualEnvironmentCertificatePrivateKey = "private_key"
mkResourceVirtualEnvironmentCertificatePublicKeySize = "public_key_size"
mkResourceVirtualEnvironmentCertificatePublicKeyType = "public_key_type"
mkResourceVirtualEnvironmentCertificateSSLFingerprint = "ssl_fingerprint"
mkResourceVirtualEnvironmentCertificateStartDate = "start_date"
mkResourceVirtualEnvironmentCertificateSubject = "subject"
mkResourceVirtualEnvironmentCertificateSubjectAlternativeNames = "subject_alternative_names"
)
func resourceVirtualEnvironmentCertificate() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
mkResourceVirtualEnvironmentCertificateCertificate: {
Type: schema.TypeString,
Description: "The PEM encoded certificate",
Required: true,
},
mkResourceVirtualEnvironmentCertificateCertificateChain: {
Type: schema.TypeString,
Description: "The PEM encoded certificate chain",
Optional: true,
Default: dvResourceVirtualEnvironmentCertificateCertificateChain,
},
mkResourceVirtualEnvironmentCertificateExpirationDate: {
Type: schema.TypeString,
Description: "The expiration date",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateFileName: {
Type: schema.TypeString,
Description: "The file name",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateIssuer: {
Type: schema.TypeString,
Description: "The issuer",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateNodeName: {
Type: schema.TypeString,
Description: "The node name",
Required: true,
ForceNew: true,
},
mkResourceVirtualEnvironmentCertificateOverwrite: {
Type: schema.TypeBool,
Description: "Whether to overwrite an existing certificate",
Optional: true,
Default: dvResourceVirtualEnvironmentCertificateOverwrite,
},
mkResourceVirtualEnvironmentCertificatePrivateKey: {
Type: schema.TypeString,
Description: "The PEM encoded private key",
Required: true,
Sensitive: true,
},
mkResourceVirtualEnvironmentCertificatePublicKeySize: {
Type: schema.TypeInt,
Description: "The public key size",
Computed: true,
},
mkResourceVirtualEnvironmentCertificatePublicKeyType: {
Type: schema.TypeString,
Description: "The public key type",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateSSLFingerprint: {
Type: schema.TypeString,
Description: "The SSL fingerprint",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateStartDate: {
Type: schema.TypeString,
Description: "The start date",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateSubject: {
Type: schema.TypeString,
Description: "The subject",
Computed: true,
},
mkResourceVirtualEnvironmentCertificateSubjectAlternativeNames: {
Type: schema.TypeList,
Description: "The subject alternative names",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
CreateContext: resourceVirtualEnvironmentCertificateCreate,
ReadContext: resourceVirtualEnvironmentCertificateRead,
UpdateContext: resourceVirtualEnvironmentCertificateUpdate,
DeleteContext: resourceVirtualEnvironmentCertificateDelete,
}
}
func resourceVirtualEnvironmentCertificateCreate(
ctx context.Context,
d *schema.ResourceData,
m interface{},
) diag.Diagnostics {
diags := resourceVirtualEnvironmentCertificateUpdate(ctx, d, m)
if diags.HasError() {
return diags
}
nodeName := d.Get(mkResourceVirtualEnvironmentCertificateNodeName).(string)
d.SetId(fmt.Sprintf("%s_certificate", nodeName))
return nil
}
func resourceVirtualEnvironmentCertificateGetUpdateBody(
d *schema.ResourceData,
) *proxmox.VirtualEnvironmentCertificateUpdateRequestBody {
certificate := d.Get(mkResourceVirtualEnvironmentCertificateCertificate).(string)
certificateChain := d.Get(mkResourceVirtualEnvironmentCertificateCertificateChain).(string)
overwrite := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentCertificateOverwrite).(bool))
privateKey := d.Get(mkResourceVirtualEnvironmentCertificatePrivateKey).(string)
combinedCertificates := strings.TrimSpace(certificate) + "\n"
if certificateChain != "" {
combinedCertificates += strings.TrimSpace(certificateChain) + "\n"
}
force := overwrite
if d.Id() != "" {
force = true
}
restart := proxmox.CustomBool(true)
body := &proxmox.VirtualEnvironmentCertificateUpdateRequestBody{
Certificates: combinedCertificates,
Force: &force,
PrivateKey: &privateKey,
Restart: &restart,
}
return body
}
func resourceVirtualEnvironmentCertificateRead(
ctx context.Context,
d *schema.ResourceData,
m interface{},
) diag.Diagnostics {
var diags diag.Diagnostics
config := m.(providerConfiguration)
veClient, err := config.GetVEClient()
if err != nil {
return diag.FromErr(err)
}
nodeName := d.Get(mkResourceVirtualEnvironmentCertificateNodeName).(string)
list, err := veClient.ListCertificates(ctx, nodeName)
if err != nil {
return diag.FromErr(err)
}
err = d.Set(mkResourceVirtualEnvironmentCertificateCertificate, "")
diags = append(diags, diag.FromErr(err)...)
err = d.Set(mkResourceVirtualEnvironmentCertificateCertificateChain, "")
diags = append(diags, diag.FromErr(err)...)
certificateChain := d.Get(mkResourceVirtualEnvironmentCertificateCertificateChain).(string)
for _, c := range *list {
if c.FileName != nil && *c.FileName == "pveproxy-ssl.pem" {
if c.Certificates != nil {
newCertificate := ""
newCertificateChain := ""
if certificateChain != "" {
certificates := strings.Split(strings.TrimSpace(*c.Certificates), "\n")
newCertificate = certificates[0] + "\n"
if len(certificates) > 1 {
newCertificateChain = strings.Join(certificates[1:], "\n") + "\n"
}
} else {
newCertificate = *c.Certificates
}
err = d.Set(mkResourceVirtualEnvironmentCertificateCertificate, newCertificate)
diags = append(diags, diag.FromErr(err)...)
err = d.Set(
mkResourceVirtualEnvironmentCertificateCertificateChain,
newCertificateChain,
)
diags = append(diags, diag.FromErr(err)...)
}
err = d.Set(mkResourceVirtualEnvironmentCertificateFileName, *c.FileName)
diags = append(diags, diag.FromErr(err)...)
if c.NotAfter != nil {
t := time.Time(*c.NotAfter)
err = d.Set(
mkResourceVirtualEnvironmentCertificateExpirationDate,
t.UTC().Format(time.RFC3339),
)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificateExpirationDate, "")
}
diags = append(diags, diag.FromErr(err)...)
if c.Issuer != nil {
err = d.Set(mkResourceVirtualEnvironmentCertificateIssuer, *c.Issuer)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificateIssuer, "")
}
diags = append(diags, diag.FromErr(err)...)
if c.PublicKeyBits != nil {
err = d.Set(mkResourceVirtualEnvironmentCertificatePublicKeySize, *c.PublicKeyBits)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificatePublicKeySize, 0)
}
diags = append(diags, diag.FromErr(err)...)
if c.PublicKeyType != nil {
pkType := *c.PublicKeyType
for _, pkt := range []string{"ecdsa", "dsa", "rsa"} {
if strings.Contains(pkType, pkt) {
pkType = pkt
}
}
err = d.Set(mkResourceVirtualEnvironmentCertificatePublicKeyType, pkType)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificatePublicKeyType, "")
}
diags = append(diags, diag.FromErr(err)...)
if c.Fingerprint != nil {
err = d.Set(mkResourceVirtualEnvironmentCertificateSSLFingerprint, *c.Fingerprint)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificateSSLFingerprint, "")
}
diags = append(diags, diag.FromErr(err)...)
if c.NotBefore != nil {
t := time.Time(*c.NotBefore)
err = d.Set(
mkResourceVirtualEnvironmentCertificateStartDate,
t.UTC().Format(time.RFC3339),
)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificateStartDate, "")
}
diags = append(diags, diag.FromErr(err)...)
if c.Subject != nil {
err = d.Set(mkResourceVirtualEnvironmentCertificateSubject, *c.Subject)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificateSubject, "")
}
diags = append(diags, diag.FromErr(err)...)
if c.SubjectAlternativeNames != nil {
sanList := make([]interface{}, len(*c.SubjectAlternativeNames))
for i, san := range *c.SubjectAlternativeNames {
sanList[i] = san
}
err = d.Set(mkResourceVirtualEnvironmentCertificateSubjectAlternativeNames, sanList)
} else {
err = d.Set(mkResourceVirtualEnvironmentCertificateSubjectAlternativeNames, []interface{}{})
}
diags = append(diags, diag.FromErr(err)...)
}
}
return diags
}
func resourceVirtualEnvironmentCertificateUpdate(
ctx context.Context,
d *schema.ResourceData,
m interface{},
) diag.Diagnostics {
config := m.(providerConfiguration)
veClient, err := config.GetVEClient()
if err != nil {
return diag.FromErr(err)
}
nodeName := d.Get(mkResourceVirtualEnvironmentCertificateNodeName).(string)
body := resourceVirtualEnvironmentCertificateGetUpdateBody(d)
err = veClient.UpdateCertificate(ctx, nodeName, body)
if err != nil {
return diag.FromErr(err)
}
return resourceVirtualEnvironmentCertificateRead(ctx, d, m)
}
func resourceVirtualEnvironmentCertificateDelete(
ctx context.Context,
d *schema.ResourceData,
m interface{},
) diag.Diagnostics {
config := m.(providerConfiguration)
veClient, err := config.GetVEClient()
if err != nil {
return diag.FromErr(err)
}
nodeName := d.Get(mkResourceVirtualEnvironmentCertificateNodeName).(string)
restart := proxmox.CustomBool(true)
err = veClient.DeleteCertificate(
ctx,
nodeName,
&proxmox.VirtualEnvironmentCertificateDeleteRequestBody{
Restart: &restart,
},
)
if err != nil {
return diag.FromErr(err)
}
d.SetId("")
return nil
}