Skip to content

Commit

Permalink
Merge pull request #51 from moulip/jpa-develop
Browse files Browse the repository at this point in the history
added config X509 resource
  • Loading branch information
bsimonWallix authored Dec 20, 2024
2 parents f0dc615 + 8476f75 commit b612c15
Show file tree
Hide file tree
Showing 5 changed files with 302 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
188 changes: 188 additions & 0 deletions bastion/resource_config_x509.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
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 {

Check failure on line 63 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

unnecessary leading newline (whitespace)

return diag.FromErr(err)
}

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

return nil
}

fillConfigX509(d, cfg)

Check failure on line 75 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

Error return value is not checked (errcheck)

return nil
}

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, _ interface{}) ([]*schema.ResourceData, error) {
// Since the resource does not have a unique ID, use the static "x509Config" ID
d.SetId("x509Config")

return []*schema.ResourceData{d}, nil
}

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

Check failure on line 116 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

return with no blank line before (nlreturn)
}

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

Check failure on line 136 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

return with no blank line before (nlreturn)
}

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

Check failure on line 149 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

return with no blank line before (nlreturn)
}

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) error {
if err := d.Set("ca_certificate", jsonData.CaCertificate); err != nil {
return err

Check failure on line 175 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

error returned from external package is unwrapped: sig: func (*github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.ResourceData).Set(key string, value interface{}) error (wrapcheck)
}
if err := d.Set("server_public_key", jsonData.ServerPublicKey); err != nil {
return err

Check failure on line 178 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

error returned from external package is unwrapped: sig: func (*github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.ResourceData).Set(key string, value interface{}) error (wrapcheck)
}
if err := d.Set("server_private_key", jsonData.ServerPrivateKey); err != nil {
return err

Check failure on line 181 in bastion/resource_config_x509.go

View workflow job for this annotation

GitHub Actions / golangci-lint

error returned from external package is unwrapped: sig: func (*github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema.ResourceData).Set(key string, value interface{}) error (wrapcheck)
}
if err := d.Set("enable", jsonData.Enable); err != nil {
return err
}

return nil
}
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.
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.
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 b612c15

Please sign in to comment.