feat: Add support for static ssh_private_key credential
This commit is contained in:
1 parent
66aad543f6
commit
445398286f
7 files changed
+561
-1
No files matched your search
@@ -0,0 +1,74 @@
|
||||
---
|
||||
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||
page_title: "boundary_credential_ssh_private_key Resource - terraform-provider-boundary"
|
||||
subcategory: ""
|
||||
description: |-
|
||||
The SSH private key credential resource allows you to configure a credential using a username, private key and optional passphrase.
|
||||
---
|
||||
|
||||
# boundary_credential_ssh_private_key (Resource)
|
||||
|
||||
The SSH private key credential resource allows you to configure a credential using a username, private key and optional passphrase.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```terraform
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "example_static_credential_store"
|
||||
description = "My first static credential store!"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_ssh_private_key" "example" {
|
||||
name = "example_ssh_private_key"
|
||||
description = "My first ssh private key credential!"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
username = "my-username"
|
||||
private_key = "my-private-key" # change to valid SSH Private Key
|
||||
private_key_passphrase = "my-optional-passphrase" # change to the passphrase of the Private Key if required
|
||||
}
|
||||
```
|
||||
|
||||
<!-- schema generated by tfplugindocs -->
|
||||
## Schema
|
||||
|
||||
### Required
|
||||
|
||||
- `credential_store_id` (String) ID of the credential store this credential belongs to.
|
||||
- `private_key` (String) The private key associated with the credential.
|
||||
- `username` (String) The username associated with the credential.
|
||||
|
||||
### Optional
|
||||
|
||||
- `description` (String) The description of the credential.
|
||||
- `name` (String) The name of the credential. Defaults to the resource name.
|
||||
- `private_key_passphrase` (String) The passphrase of the private key associated with the credential.
|
||||
|
||||
### Read-Only
|
||||
|
||||
- `id` (String) The ID of the credential.
|
||||
- `private_key_hmac` (String) The private key hmac.
|
||||
- `private_key_passphrase_hmac` (String) The private key passphrase hmac.
|
||||
|
||||
## Import
|
||||
|
||||
Import is supported using the following syntax:
|
||||
|
||||
```shell
|
||||
terraform import boundary_credential_ssh_private_key.example_ssh_private_key <my-id>
|
||||
```
|
||||
@@ -0,0 +1 @@
|
||||
terraform import boundary_credential_ssh_private_key.example_ssh_private_key <my-id>
|
||||
@@ -0,0 +1,29 @@
|
||||
resource "boundary_scope" "org" {
|
||||
name = "organization_one"
|
||||
description = "global scope"
|
||||
scope_id = "global"
|
||||
auto_create_admin_role = true
|
||||
auto_create_default_role = true
|
||||
}
|
||||
|
||||
resource "boundary_scope" "project" {
|
||||
name = "project_one"
|
||||
description = "My first scope!"
|
||||
scope_id = boundary_scope.org.id
|
||||
auto_create_admin_role = true
|
||||
}
|
||||
|
||||
resource "boundary_credential_store_static" "example" {
|
||||
name = "example_static_credential_store"
|
||||
description = "My first static credential store!"
|
||||
scope_id = boundary_scope.project.id
|
||||
}
|
||||
|
||||
resource "boundary_credential_ssh_private_key" "example" {
|
||||
name = "example_ssh_private_key"
|
||||
description = "My first ssh private key credential!"
|
||||
credential_store_id = boundary_credential_store_static.example.id
|
||||
username = "my-username"
|
||||
private_key = "my-private-key" # change to valid SSH Private Key
|
||||
private_key_passphrase = "my-optional-passphrase" # change to the passphrase of the Private Key if required
|
||||
}
|
||||
@@ -72,6 +72,7 @@ func New() *schema.Provider {
|
||||
"boundary_credential_store_vault": resourceCredentialStoreVault(),
|
||||
"boundary_credential_store_static": resourceCredentialStoreStatic(),
|
||||
"boundary_credential_username_password": resourceCredentialUsernamePassword(),
|
||||
"boundary_credential_ssh_private_key": resourceCredentialSshPrivateKey(),
|
||||
"boundary_managed_group": resourceManagedGroup(),
|
||||
"boundary_group": resourceGroup(),
|
||||
"boundary_host": resourceHost(),
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentiallibraries"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
)
|
||||
|
||||
const (
|
||||
credentialSshPrivateKeyUsernameKey = "username"
|
||||
credentialSshPrivateKeyPrivateKeyKey = "private_key"
|
||||
credentialSshPrivateKeyPrivateKeyHmacKey = "private_key_hmac"
|
||||
credentialSshPrivateKeyPassphraseKey = "private_key_passphrase"
|
||||
credentialSshPrivateKeyPassphraseHmacKey = "private_key_passphrase_hmac"
|
||||
credentialSshPrivateKeyCredentialType = "ssh_private_key"
|
||||
)
|
||||
|
||||
func resourceCredentialSshPrivateKey() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Description: "The SSH private key credential resource allows you to configure a credential using a username, private key and optional passphrase.",
|
||||
|
||||
CreateContext: resourceCredentialSshPrivateKeyCreate,
|
||||
ReadContext: resourceCredentialSshPrivateKeyRead,
|
||||
UpdateContext: resourceCredentialSshPrivateKeyUpdate,
|
||||
DeleteContext: resourceCredentialSshPrivateKeyDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
StateContext: schema.ImportStatePassthroughContext,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
IDKey: {
|
||||
Description: "The ID of the credential.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
NameKey: {
|
||||
Description: "The name of the credential. Defaults to the resource name.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
DescriptionKey: {
|
||||
Description: "The description of the credential.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
credentialStoreIdKey: {
|
||||
Description: "ID of the credential store this credential belongs to.",
|
||||
Type: schema.TypeString,
|
||||
ForceNew: true,
|
||||
Required: true,
|
||||
},
|
||||
credentialSshPrivateKeyUsernameKey: {
|
||||
Description: "The username associated with the credential.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
credentialSshPrivateKeyPrivateKeyKey: {
|
||||
Description: "The private key associated with the credential.",
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
credentialSshPrivateKeyPrivateKeyHmacKey: {
|
||||
Description: "The private key hmac.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
credentialSshPrivateKeyPassphraseKey: {
|
||||
Description: "The passphrase of the private key associated with the credential.",
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
credentialSshPrivateKeyPassphraseHmacKey: {
|
||||
Description: "The private key passphrase hmac.",
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func setFromCredentialSshPrivateKeyResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if attrsVal, ok := raw["attributes"]; ok {
|
||||
attrs := attrsVal.(map[string]interface{})
|
||||
if err := d.Set(credentialSshPrivateKeyUsernameKey, attrs[credentialSshPrivateKeyUsernameKey]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
statePrivKeyHmac := d.Get(credentialSshPrivateKeyPrivateKeyHmacKey)
|
||||
boundaryPrivKeyHmac := attrs[credentialSshPrivateKeyPrivateKeyHmacKey].(string)
|
||||
if statePrivKeyHmac.(string) != boundaryPrivKeyHmac && fromRead {
|
||||
// PrivateKeyHmac has changed in Boundary, therefore the private key has changed.
|
||||
// Update private key value to force tf to attempt update.
|
||||
if err := d.Set(credentialSshPrivateKeyPrivateKeyKey, "(changed in Boundary)"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.Set(credentialSshPrivateKeyPrivateKeyHmacKey, boundaryPrivKeyHmac); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var statePassphraseHmac, boundaryPassphraseHmac string
|
||||
if v := d.Get(credentialSshPrivateKeyPassphraseHmacKey); v != nil {
|
||||
statePassphraseHmac = v.(string)
|
||||
}
|
||||
if v := attrs[credentialSshPrivateKeyPassphraseHmacKey]; v != nil {
|
||||
boundaryPassphraseHmac = v.(string)
|
||||
}
|
||||
if statePassphraseHmac != boundaryPassphraseHmac && fromRead {
|
||||
// PassphraseHmac has changed in Boundary, therefore the private key passphrase has changed.
|
||||
// Update private key passphrase value to force tf to attempt update.
|
||||
if err := d.Set(credentialSshPrivateKeyPassphraseKey, "(changed in Boundary)"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := d.Set(credentialSshPrivateKeyPassphraseHmacKey, boundaryPassphraseHmac); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
d.SetId(raw["id"].(string))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialSshPrivateKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
|
||||
var opts []credentials.Option
|
||||
if v, ok := d.GetOk(NameKey); ok {
|
||||
opts = append(opts, credentials.WithName(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(credentialSshPrivateKeyUsernameKey); ok {
|
||||
opts = append(opts, credentials.WithSshPrivateKeyCredentialUsername(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(credentialSshPrivateKeyPrivateKeyKey); ok {
|
||||
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKey(v.(string)))
|
||||
}
|
||||
if v, ok := d.GetOk(credentialSshPrivateKeyPassphraseKey); ok {
|
||||
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKeyPassphrase(v.(string)))
|
||||
}
|
||||
|
||||
var credentialStoreId string
|
||||
retrievedStoreId, ok := d.GetOk(credentialStoreIdKey)
|
||||
if ok {
|
||||
credentialStoreId = retrievedStoreId.(string)
|
||||
} else {
|
||||
return diag.Errorf("credential store id is unset")
|
||||
}
|
||||
|
||||
client := credentials.NewClient(md.client)
|
||||
cr, err := client.Create(ctx, credentialSshPrivateKeyCredentialType, credentialStoreId, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error creating credential: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("nil credential after create")
|
||||
}
|
||||
|
||||
if err := setFromCredentialSshPrivateKeyResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialSshPrivateKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
cr, err := client.Read(ctx, d.Id())
|
||||
if err != nil {
|
||||
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
return diag.Errorf("error reading credential: %v", err)
|
||||
}
|
||||
if cr == nil {
|
||||
return diag.Errorf("credential nil after read")
|
||||
}
|
||||
|
||||
if err := setFromCredentialSshPrivateKeyResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialSshPrivateKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
var opts []credentials.Option
|
||||
if d.HasChange(NameKey) {
|
||||
opts = append(opts, credentials.DefaultName())
|
||||
nameVal, ok := d.GetOk(NameKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithName(nameVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(DescriptionKey) {
|
||||
opts = append(opts, credentials.DefaultDescription())
|
||||
descVal, ok := d.GetOk(DescriptionKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithDescription(descVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(credentialSshPrivateKeyUsernameKey) {
|
||||
usernameVal, ok := d.GetOk(credentialSshPrivateKeyUsernameKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithSshPrivateKeyCredentialUsername(usernameVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(credentialSshPrivateKeyPrivateKeyKey) {
|
||||
privKeyVal, ok := d.GetOk(credentialSshPrivateKeyPrivateKeyKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKey(privKeyVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if d.HasChange(credentialSshPrivateKeyPassphraseKey) {
|
||||
passVal, ok := d.GetOk(credentialSshPrivateKeyPassphraseKey)
|
||||
if ok {
|
||||
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKeyPassphrase(passVal.(string)))
|
||||
}
|
||||
}
|
||||
|
||||
if len(opts) > 0 {
|
||||
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||
crUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||
if err != nil {
|
||||
return diag.Errorf("error updating credential: %v", err)
|
||||
}
|
||||
if crUpdate == nil {
|
||||
return diag.Errorf("credential nil after update")
|
||||
}
|
||||
|
||||
if err = setFromCredentialSshPrivateKeyResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
||||
return diag.Errorf("error generating credential from response map: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func resourceCredentialSshPrivateKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||
md := meta.(*metaData)
|
||||
client := credentials.NewClient(md.client)
|
||||
|
||||
_, err := client.Delete(ctx, d.Id())
|
||||
if err != nil {
|
||||
return diag.Errorf("error deleting credential: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/credentials"
|
||||
"github.com/hashicorp/boundary/testing/controller"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||
"golang.org/x/crypto/ssh/testdata"
|
||||
)
|
||||
|
||||
const (
|
||||
sshPrivateKeyCredResc = "boundary_credential_ssh_private_key.example"
|
||||
sshPrivateKeyCredName = "Dr Jekyll"
|
||||
sshPrivateKeyCredDesc = "my best description"
|
||||
sshPrivateKeyUpdate = "some magic update string"
|
||||
sshPrivateKeyUsername = "my-user"
|
||||
)
|
||||
|
||||
var staticStore = fmt.Sprintf(`
|
||||
resource "boundary_credential_store_static" "ssh_store" {
|
||||
name = "static store name"
|
||||
description = "static store description"
|
||||
scope_id = boundary_scope.proj1.id
|
||||
depends_on = [boundary_role.proj1_admin]
|
||||
}`)
|
||||
|
||||
func sshPrivateKeyResource(name, description, username, privateKey, passphrase string) string {
|
||||
return fmt.Sprintf(`
|
||||
resource "boundary_credential_ssh_private_key" "example" {
|
||||
name = %q
|
||||
description = %q
|
||||
credential_store_id = boundary_credential_store_static.ssh_store.id
|
||||
username = %q
|
||||
private_key = %q
|
||||
private_key_passphrase = %q
|
||||
}`, name, description, username, privateKey, passphrase)
|
||||
}
|
||||
|
||||
func TestAccCredentialSshPrivateKey(t *testing.T) {
|
||||
tc := controller.NewTestController(t, tcConfig...)
|
||||
defer tc.Shutdown()
|
||||
url := tc.ApiAddrs()[0]
|
||||
|
||||
privKey := string(testdata.PEMBytes["rsa"])
|
||||
privKeyUpdate := string(testdata.PEMEncryptedKeys[0].PEMBytes)
|
||||
privKeyUpdatePassphrase := testdata.PEMEncryptedKeys[0].EncryptionKey
|
||||
|
||||
res := sshPrivateKeyResource(
|
||||
sshPrivateKeyCredName,
|
||||
sshPrivateKeyCredDesc,
|
||||
sshPrivateKeyUsername,
|
||||
privKey,
|
||||
"",
|
||||
)
|
||||
|
||||
resUpdate := sshPrivateKeyResource(
|
||||
sshPrivateKeyCredName+sshPrivateKeyUpdate,
|
||||
sshPrivateKeyCredDesc+sshPrivateKeyUpdate,
|
||||
sshPrivateKeyUsername+sshPrivateKeyUpdate,
|
||||
privKeyUpdate,
|
||||
privKeyUpdatePassphrase,
|
||||
)
|
||||
|
||||
var provider *schema.Provider
|
||||
resource.Test(t, resource.TestCase{
|
||||
IsUnitTest: true,
|
||||
ProviderFactories: providerFactories(&provider),
|
||||
CheckDestroy: testAccCheckCredentialSshPrivateKeyResourceDestroy(t, provider),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
// create
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, staticStore, res),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, NameKey, sshPrivateKeyCredName),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, DescriptionKey, sshPrivateKeyCredDesc),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyUsernameKey, sshPrivateKeyUsername),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPrivateKeyKey, privKey),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPassphraseKey, ""),
|
||||
|
||||
testAccCheckCredentialStoreSshPrivateKeyHmac(provider),
|
||||
testAccCheckCredentialSshPrivateKeyResourceExists(provider, sshPrivateKeyCredResc),
|
||||
),
|
||||
},
|
||||
importStep(sshPrivateKeyCredResc, credentialSshPrivateKeyPrivateKeyKey, credentialSshPrivateKeyPassphraseKey),
|
||||
{
|
||||
// update
|
||||
Config: testConfig(url, fooOrg, firstProjectFoo, staticStore, resUpdate),
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, NameKey, sshPrivateKeyCredName+sshPrivateKeyUpdate),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, DescriptionKey, sshPrivateKeyCredDesc+sshPrivateKeyUpdate),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyUsernameKey, sshPrivateKeyUsername+sshPrivateKeyUpdate),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPrivateKeyKey, privKeyUpdate),
|
||||
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPassphraseKey, privKeyUpdatePassphrase),
|
||||
|
||||
testAccCheckCredentialStoreSshPrivateKeyHmac(provider),
|
||||
testAccCheckCredentialSshPrivateKeyResourceExists(provider, sshPrivateKeyCredResc),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccCheckCredentialSshPrivateKeyResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[name]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found: %s", name)
|
||||
}
|
||||
|
||||
id := rs.Primary.ID
|
||||
if id == "" {
|
||||
return fmt.Errorf("no ID is set")
|
||||
}
|
||||
storeId = id
|
||||
|
||||
md := testProvider.Meta().(*metaData)
|
||||
c := credentials.NewClient(md.client)
|
||||
if _, err := c.Read(context.Background(), id); err != nil {
|
||||
return fmt.Errorf("got an error reading %q: %w", id, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckCredentialSshPrivateKeyResourceDestroy(t *testing.T, testProvider *schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
if testProvider.Meta() == nil {
|
||||
t.Fatal("got nil provider metadata")
|
||||
}
|
||||
md := testProvider.Meta().(*metaData)
|
||||
|
||||
for _, rs := range s.RootModule().Resources {
|
||||
switch rs.Type {
|
||||
case "boundary_credential_ssh_private_key":
|
||||
id := rs.Primary.ID
|
||||
|
||||
c := credentials.NewClient(md.client)
|
||||
_, err := c.Read(context.Background(), id)
|
||||
if apiErr := api.AsServerError(err); apiErr == nil || apiErr.Response().StatusCode() != http.StatusNotFound {
|
||||
return fmt.Errorf("didn't get a 404 when reading destroyed credential %q: %v", id, err)
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccCheckCredentialStoreSshPrivateKeyHmac(testProvider *schema.Provider) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[sshPrivateKeyCredResc]
|
||||
if !ok {
|
||||
return fmt.Errorf("not found: %s", sshPrivateKeyCredResc)
|
||||
}
|
||||
|
||||
computed := rs.Primary.Attributes["private_key_hmac"]
|
||||
if len(computed) != 43 {
|
||||
return fmt.Errorf("computed private key hmac not the expected length of 43 characters, got: %q", computed)
|
||||
}
|
||||
|
||||
if rs.Primary.Attributes["private_key_passphrase"] != "" {
|
||||
// We set a passphrase, validate the computed hmac is expected length
|
||||
computed := rs.Primary.Attributes["private_key_passphrase_hmac"]
|
||||
if len(computed) != 43 {
|
||||
return fmt.Errorf("computed private key passphrase hmac not the expected length of 43 characters, got: %q", computed)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user