Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added config X509 resource #51

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
```
Loading