-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #51 from moulip/jpa-develop
added config X509 resource
- Loading branch information
Showing
5 changed files
with
302 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 { | ||
|
||
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) | ||
|
||
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 | ||
} | ||
|
||
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) error { | ||
if err := d.Set("ca_certificate", jsonData.CaCertificate); err != nil { | ||
return err | ||
Check failure on line 175 in bastion/resource_config_x509.go GitHub Actions / golangci-lint
|
||
} | ||
if err := d.Set("server_public_key", jsonData.ServerPublicKey); err != nil { | ||
return err | ||
Check failure on line 178 in bastion/resource_config_x509.go GitHub Actions / golangci-lint
|
||
} | ||
if err := d.Set("server_private_key", jsonData.ServerPrivateKey); err != nil { | ||
return err | ||
Check failure on line 181 in bastion/resource_config_x509.go GitHub Actions / golangci-lint
|
||
} | ||
if err := d.Set("enable", jsonData.Enable); err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
`) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` |