Skip to content

Commit

Permalink
added config X509 resource
Browse files Browse the repository at this point in the history
  • Loading branch information
Julien committed Dec 20, 2024
1 parent 59d1030 commit 1bfb3b2
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changes/feature_config_x509.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
FEATURES:

* **resource/wallix-bastion_config_x509**: added the possibilty to configure the X509 for the GUI and for users authentication
1 change: 1 addition & 0 deletions bastion/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func Provider() *schema.Provider {
"wallix-bastion_authorization": resourceAuthorization(),
"wallix-bastion_checkout_policy": resourceCheckoutPolicy(),
"wallix-bastion_cluster": resourceCluster(),
"wallix-bastion_config_x509": resourceConfigX509(),
"wallix-bastion_connection_message": resourceConnectionMessage(),
"wallix-bastion_connection_policy": resourceConnectionPolicy(),
"wallix-bastion_device": resourceDevice(),
Expand Down
174 changes: 174 additions & 0 deletions bastion/resource_config_x509.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package bastion

import (
"context"
"encoding/json"
"fmt"
"net/http"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

type jsonConfigX509 struct {
CaCertificate string `json:"ca_certificate,omitempty"`
ServerPublicKey string `json:"server_public_key"`
ServerPrivateKey string `json:"server_private_key"`
Enable bool `json:"enable,omitempty"`
}

func resourceConfigX509() *schema.Resource {
return &schema.Resource{
CreateContext: resourceConfigX509Create,
ReadContext: resourceConfigX509Read,
UpdateContext: resourceConfigX509Update,
DeleteContext: resourceConfigX509Delete,
Importer: &schema.ResourceImporter{
State: resourceConfigX509Import,
},
Schema: map[string]*schema.Schema{
"ca_certificate": {
Type: schema.TypeString,
Optional: true,
},
"server_public_key": {
Type: schema.TypeString,
Required: true,
},
"server_private_key": {
Type: schema.TypeString,
Required: true,
},
"enable": {
Type: schema.TypeBool,
Optional: true,
},
},
}
}

func resourceConfigX509Create(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
// Add the configuration
if err := addConfigX509(ctx, d, m); err != nil {
return diag.FromErr(err)
}
// Use a static ID since the API does not provide one
d.SetId("x509Config")

return resourceConfigX509Read(ctx, d, m)
}

func resourceConfigX509Read(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
cfg, err := readConfigX509Options(ctx, m)
if err != nil {
return diag.FromErr(err)
}

// If no config exists, mark the resource as deleted
if cfg.ServerPublicKey == "" && cfg.ServerPrivateKey == "" {
d.SetId("")
return nil

Check failure on line 70 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

return with no blank line before (nlreturn)
}

fillConfigX509(d, cfg)
return nil

Check failure on line 74 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

return with no blank line before (nlreturn)
}

func resourceConfigX509Update(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
if err := updateConfigX509(ctx, d, m); err != nil {
return diag.FromErr(err)
}

return resourceConfigX509Read(ctx, d, m)
}

func resourceConfigX509Delete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
if err := deleteConfigX509(ctx, m); err != nil {
return diag.FromErr(err)
}

// Remove the resource from state
d.SetId("")

return nil
}

func resourceConfigX509Import(d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) {

Check failure on line 96 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

unused-parameter: parameter 'm' seems to be unused, consider removing or renaming it as _ (revive)
// Since the resource does not have a unique ID, use the static "x509Config" ID
d.SetId("x509Config")
return []*schema.ResourceData{d}, nil

Check failure on line 99 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

return with no blank line before (nlreturn)
}

func addConfigX509(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*Client)
jsonData := prepareConfigX509JSON(d)
body, code, err := c.newRequest(ctx, "/config/x509", http.MethodPost, jsonData)
if err != nil {
return err
}
if code != http.StatusOK && code != http.StatusNoContent {
return fmt.Errorf("API returned error: %d with body:\n%s", code, body)
}
return nil
}

func readConfigX509Options(ctx context.Context, m interface{}) (jsonConfigX509, error) {
c := m.(*Client)
var result jsonConfigX509
body, code, err := c.newRequest(ctx, "/config/x509", http.MethodGet, nil)
if err != nil {
return result, err
}
if code == http.StatusNotFound {
return result, nil
}
if code != http.StatusOK {
return result, fmt.Errorf("API returned error: %d with body:\n%s", code, body)
}
err = json.Unmarshal([]byte(body), &result)
if err != nil {
return result, fmt.Errorf("error unmarshaling JSON: %w", err)
}
return result, nil
}

func updateConfigX509(ctx context.Context, d *schema.ResourceData, m interface{}) error {
c := m.(*Client)
jsonData := prepareConfigX509JSON(d)
body, code, err := c.newRequest(ctx, "/config/x509", http.MethodPut, jsonData)
if err != nil {
return err
}
if code != http.StatusOK && code != http.StatusNoContent {
return fmt.Errorf("API returned error: %d with body:\n%s", code, body)
}
return nil
}

func deleteConfigX509(ctx context.Context, m interface{}) error {
c := m.(*Client)
body, code, err := c.newRequest(ctx, "/config/x509", http.MethodDelete, nil)
if err != nil {
return err
}
if code != http.StatusOK && code != http.StatusNoContent {
return fmt.Errorf("API returned error: %d with body:\n%s", code, body)
}
return nil
}

func prepareConfigX509JSON(d *schema.ResourceData) jsonConfigX509 {
return jsonConfigX509{
CaCertificate: d.Get("ca_certificate").(string),
ServerPublicKey: d.Get("server_public_key").(string),
ServerPrivateKey: d.Get("server_private_key").(string),
Enable: d.Get("enable").(bool),
}
}

func fillConfigX509(d *schema.ResourceData, jsonData jsonConfigX509) {
d.Set("ca_certificate", jsonData.CaCertificate)

Check failure on line 170 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Error return value of `d.Set` is not checked (errcheck)
d.Set("server_public_key", jsonData.ServerPublicKey)

Check failure on line 171 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Error return value of `d.Set` is not checked (errcheck)
d.Set("server_private_key", jsonData.ServerPrivateKey)

Check failure on line 172 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Error return value of `d.Set` is not checked (errcheck)
d.Set("enable", jsonData.Enable)
}
63 changes: 63 additions & 0 deletions bastion/resource_config_x509_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package bastion_test

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

// TestAccResourceConfigX509_basic tests creating, updating the x509 configuration.
func TestAccResourceConfigX509_basic(t *testing.T) {
resourceName := "bastion_x509_config.test"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) }, // Ensures necessary environment variables are set
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccResourceConfigX509Basic(),
Check: resource.ComposeTestCheckFunc(
// Verify that the resource exists
resource.TestCheckResourceAttr(resourceName, "ca_certificate", "test-ca-cert"),
resource.TestCheckResourceAttr(resourceName, "server_public_key", "test-public-key"),
resource.TestCheckResourceAttr(resourceName, "server_private_key", "test-private-key"),
resource.TestCheckResourceAttr(resourceName, "enable", "true"),
),
},
// Test updating the resource
{
Config: testAccResourceConfigX509Update(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "ca_certificate", "updated-ca-cert"),
resource.TestCheckResourceAttr(resourceName, "server_public_key", "updated-public-key"),
resource.TestCheckResourceAttr(resourceName, "server_private_key", "updated-private-key"),
resource.TestCheckResourceAttr(resourceName, "enable", "false"),
),
},
},
})
}

// Test configuration for creating the resource

Check failure on line 41 in bastion/resource_config_x509_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Comment should end in a period (godot)
func testAccResourceConfigX509Basic() string {
return (`
resource "bastion_x509_config" "test" {
ca_certificate = "test-ca-cert"
server_public_key = "test-public-key"
server_private_key = "test-private-key"
enable = true
}
`)
}

// Test configuration for updating the resource

Check failure on line 53 in bastion/resource_config_x509_test.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Comment should end in a period (godot)
func testAccResourceConfigX509Update() string {
return (`
resource "bastion_x509_config" "test" {
ca_certificate = "updated-ca-cert"
server_public_key = "updated-public-key"
server_private_key = "updated-private-key"
enable = false
}
`)
}
47 changes: 47 additions & 0 deletions docs/resources/config_x509.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# wallix-bastion_config_x509 Resource

Provides a X509 resource.

## Example Usage

```hcl
# Configure the X509 authentication and/or change GUI and API certificates
resource "wallix-bastion_config_x509" "acme-cert" {
ca_certificate = file("${path.root}/chain1.pem")
server_private_key = file("${path.root}/privkey1.pem")
server_public_key = file("${path.root}/cert1.pem")
enable = true
}
```

## Argument Reference

The following arguments are supported:

- **ca_certificate** (Optional, String)
The ca for users authentication
- **server_private_key** (Required, String)
The server certificate private key
- **server_public_key** (Required, String)
The server certificate public key
- **enable** (Optional, Bool)
Whether or not enable X509 users authentication

## Attribute Reference

- **id** (String)
Internal id of X509 config (only in Tfstate since the API does not provide any)
- **ca_certificate** (String)
The server X509 ca certificate for users authentication
- **server_public_key** (String)
The server x509 public certificate
- **enable** (String)
Whether or not the X509 users authentication is enabled

## Import

X509 config can be imported using any id (in Tfstate it will always be x509Config ) e.g.

```shell
terraform import wallix-bastion_device.acme-cert myx509
```

0 comments on commit 1bfb3b2

Please sign in to comment.