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

Add BYOK resource #330

Merged
merged 7 commits into from
May 23, 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
49 changes: 49 additions & 0 deletions docs/data-sources/cloud_accounts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "astra_cloud_accounts Data Source - terraform-provider-astra"
subcategory: ""
description: |-
Retrieve a list of Cloud Accounts within an Organization
---

# astra_cloud_accounts (Data Source)

Retrieve a list of Cloud Accounts within an Organization

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably more a of a question for the DevOps API folks, but will this only ever return an array of length 1, or are there situations where Astra organizations will have more than one cloud accounts for a given cloud provider and region?

I ask since the primary use case for this data source is to be able to feed it into an AWS KMS access policy, which would require creating an ARN based on the provider_id returned in this data source's response. I'm curious if it is safe to just refer to it with data.astra_cloud_accounts.this[0].provider_id, or if some HCL manipulation needs to be done to turn it into an array of provider IDs/ARNs for the KMS key policy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For GCP, I happen to have 2 accounts, so it can be more than 1. That may only be the case for GCP, but the code handles both AWS and GCP.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can happen to aws too.


## Example Usage

```terraform
# AWS example
data "astra_cloud_accounts" "awsaccounts" {
cloud_provider = "aws"
region = "us-east-1"
}

# GCP example
data "astra_cloud_accounts" "gcpaccounts" {
cloud_provider = "gcp"
region = "us-east1"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `cloud_provider` (String) The cloud provider where the Customer Key exists (Currently supported: aws, gcp)
- `region` (String) Cloud provider region

### Read-Only

- `id` (String) The ID of this resource.
- `results` (List of Object) The list of Cloud Accounts for the given Organization. (see [below for nested schema](#nestedatt--results))

<a id="nestedatt--results"></a>
### Nested Schema for `results`

Read-Only:

- `organization_id` (String)
- `provider` (String)
- `provider_id` (String)
35 changes: 35 additions & 0 deletions docs/data-sources/customer_key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "astra_customer_key Data Source - terraform-provider-astra"
subcategory: ""
description: |-
Retrieve a Customer Key for a given cloud provider and region
---

# astra_customer_key (Data Source)

Retrieve a Customer Key for a given cloud provider and region

## Example Usage

```terraform
# Read in a customer key for a given cloud provider and region
data "astra_customer_key" "key" {
cloud_provider = "aws"
region = "us-east-1"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `cloud_provider` (String) The cloud provider where the Customer Key exists (Currently supported: aws, gcp)
- `region` (String) Cloud provider region

### Read-Only

- `id` (String) The ID of this resource.
- `key_id` (String) The Customer Key ID
- `organization_id` (String) Organization ID
37 changes: 37 additions & 0 deletions docs/data-sources/customer_keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "astra_customer_keys Data Source - terraform-provider-astra"
subcategory: ""
description: |-
Retrieve a list of Customer Keys within an Organization
---

# astra_customer_keys (Data Source)

Retrieve a list of Customer Keys within an Organization

## Example Usage

```terraform
# Read in all customer keys for the given Organization
data "astra_customer_keys" "keys" {
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Read-Only

- `id` (String) The ID of this resource.
- `results` (List of Object) The list of Customer Keys for the given Organization. (see [below for nested schema](#nestedatt--results))

<a id="nestedatt--results"></a>
### Nested Schema for `results`

Read-Only:

- `cloud_provider` (String)
- `key_id` (String)
- `organization_id` (String)
- `region` (String)
2 changes: 1 addition & 1 deletion docs/data-sources/database.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ data "astra_database" "db" {
- `keyspace` (String) Initial keyspace
- `name` (String) Database name (user provided)
- `node_count` (Number) Node count (not relevant for serverless databases)
- `organization_id` (String) Ordg id (system generated)
- `organization_id` (String) Organization id (system generated)
- `owner_id` (String) Owner id (system generated)
- `regions` (List of String) Cloud provider region. Get list of supported regions from regions data-source
- `replication_factor` (Number) Replication Factor (not relevant for serverless databases)
Expand Down
2 changes: 1 addition & 1 deletion docs/data-sources/databases.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ output "existing_dbs" {
### Optional

- `cloud_provider` (String) The cloud provider
- `status` (String) Status flter. Only return databases with matching status, if supplied. Otherwise return all databases matching other requirements
- `status` (String) Status filter. Only return databases with matching status, if supplied. Otherwise return all databases matching other requirements

### Read-Only

Expand Down
52 changes: 52 additions & 0 deletions docs/resources/customer_key.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "astra_customer_key Resource - terraform-provider-astra"
subcategory: ""
description: |-
astra_customer_key provides a Customer Key resource for Astra's Bring Your Own Key (BYOK). Note that DELETE is not supported through Terraform currently. A support ticket must be created to delete Customer Keys in Astra. WARNING: Deleting a key from Astra will result in an outage. Please see https://docs.datastax.com/en/astra-db-serverless/administration/delete-customer-keys.html for more information.
---

# astra_customer_key (Resource)

`astra_customer_key` provides a Customer Key resource for Astra's Bring Your Own Key (BYOK). Note that DELETE is not supported through Terraform currently. A support ticket must be created to delete Customer Keys in Astra. WARNING: Deleting a key from Astra will result in an outage. Please see https://docs.datastax.com/en/astra-db-serverless/administration/delete-customer-keys.html for more information.

## Example Usage

```terraform
# AWS example
resource "astra_customer_key" "customerkey" {
cloud_provider = "aws"
region = "us-east-1"
key_id = "arn:aws:kms:us-east-1:123456789012:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
}

# GCP example
resource "astra_customer_key" "customerKey" {
cloud_provider = "gcp"
region = "us-east1"
key_id = "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key"
}
```

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `cloud_provider` (String) The cloud provider where the Customer Key exists (Currently supported: aws, gcp)
- `key_id` (String) Customer Key ID. This is cloud provider specific.
- `region` (String) Region in which the Customer Key exists.

### Read-Only

- `id` (String) The ID of this resource.
- `organization_id` (String) The Astra organization ID (this is derived from the token used to create the Customer Key).

## Import

Import is supported using the following syntax:

```shell
# the import id is in the fomrat of <orgId>/cloudProvider/<cloud_provider>/region/<region>/keyId/<key_id>
terraform import astra_customer_key.customerkey 4d3c2b1a-5e6f-1a2b-3c4d-5e6f1a2b3c4d/cloudProvider/aws/region/us-east-1/keyId/arn:aws:kms:us-east-1:123456789012:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d
```
11 changes: 11 additions & 0 deletions examples/data-sources/astra_cloud_accounts/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# AWS example
data "astra_cloud_accounts" "awsaccounts" {
cloud_provider = "aws"
region = "us-east-1"
}

# GCP example
data "astra_cloud_accounts" "gcpaccounts" {
cloud_provider = "gcp"
region = "us-east1"
}
5 changes: 5 additions & 0 deletions examples/data-sources/astra_customer_key/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Read in a customer key for a given cloud provider and region
data "astra_customer_key" "key" {
cloud_provider = "aws"
region = "us-east-1"
}
3 changes: 3 additions & 0 deletions examples/data-sources/astra_customer_keys/data-source.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Read in all customer keys for the given Organization
data "astra_customer_keys" "keys" {
}
2 changes: 2 additions & 0 deletions examples/resources/astra_customer_key/import.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# the import id is in the fomrat of <orgId>/cloudProvider/<cloud_provider>/region/<region>/keyId/<key_id>
terraform import astra_customer_key.customerkey 4d3c2b1a-5e6f-1a2b-3c4d-5e6f1a2b3c4d/cloudProvider/aws/region/us-east-1/keyId/arn:aws:kms:us-east-1:123456789012:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d
13 changes: 13 additions & 0 deletions examples/resources/astra_customer_key/resource.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# AWS example
resource "astra_customer_key" "customerkey" {
cloud_provider = "aws"
region = "us-east-1"
key_id = "arn:aws:kms:us-east-1:123456789012:key/1a2b3c4d-5e6f-1a2b-3c4d-5e6f1a2b3c4d"
}

# GCP example
resource "astra_customer_key" "customerKey" {
cloud_provider = "gcp"
region = "us-east1"
key_id = "projects/my-project/locations/us-east1/keyRings/my-key-ring/cryptoKeys/my-key"
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.21
toolchain go1.22.0

require (
github.com/datastax/astra-client-go/v2 v2.2.53
github.com/datastax/astra-client-go/v2 v2.2.54
github.com/datastax/pulsar-admin-client-go v0.0.0-20230707040954-1a4745e07587
github.com/google/uuid v1.6.0
github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/datastax/astra-client-go/v2 v2.2.53 h1:qWCBksV9rWi9WmSBW71IGhy3mL/QwkEw1BMG42ph540=
github.com/datastax/astra-client-go/v2 v2.2.53/go.mod h1:zxXWuqDkYia7PzFIL3T7RmjChc9LN81UnfI2yB4kE7M=
github.com/datastax/astra-client-go/v2 v2.2.54 h1:R2k9ek9zaU15cLD96np5gsj12oZhK3Z5/tSytjQagO8=
github.com/datastax/astra-client-go/v2 v2.2.54/go.mod h1:zxXWuqDkYia7PzFIL3T7RmjChc9LN81UnfI2yB4kE7M=
github.com/datastax/pulsar-admin-client-go v0.0.0-20230707040954-1a4745e07587 h1:3jv+O0hWcz3oj3sZ9/Ov9/m1Vaqx8Ql8jp5ZeA13O5A=
github.com/datastax/pulsar-admin-client-go v0.0.0-20230707040954-1a4745e07587/go.mod h1:guL8YZ5gJINN+h5Kmja1AnuzhxLU3sHQL8o/8HYLtqk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down
101 changes: 101 additions & 0 deletions internal/provider/data_source_cloud_accounts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package provider

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

"github.com/datastax/astra-client-go/v2/astra"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/id"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func dataSourceCloudAccounts() *schema.Resource {
return &schema.Resource{
Description: "Retrieve a list of Cloud Accounts within an Organization",

ReadContext: dataSourceCloudAccountsRead,

Schema: map[string]*schema.Schema{
// Required inputs
"cloud_provider": {
Description: "The cloud provider where the Customer Key exists (Currently supported: aws, gcp)",
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice(availableBYOKCloudProviders, true),
DiffSuppressFunc: ignoreCase,
},
"region": {
Description: "Cloud provider region",
Type: schema.TypeString,
Required: true,
},
// Computed outputs
"results": {
Type: schema.TypeList,
Description: "The list of Cloud Accounts for the given Organization.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"organization_id": {
Description: "Organization ID",
Type: schema.TypeString,
Computed: true,
},
"provider": {
Description: "The cloud provider",
Type: schema.TypeString,
Required: true,
},
"provider_id": {
Description: "The provider account ID",
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func dataSourceCloudAccountsRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client := meta.(astraClients).astraClient.(*astra.ClientWithResponses)
provider := d.Get("cloud_provider").(string)
region := d.Get("region").(string)

cloudAccounts, err := listCloudAccounts(ctx, client, provider, region)
if err != nil {
return diag.FromErr(err)
}

if err := d.Set("results", cloudAccounts); err != nil {
return diag.FromErr(err)
}

d.SetId(id.UniqueId())
return nil
}

func listCloudAccounts(ctx context.Context, client *astra.ClientWithResponses, cloudProvider, region string) ([]map[string]interface{}, error) {
resp, err := client.GetCloudAccountsWithResponse(ctx, cloudProvider, region)
if err != nil {
return nil, err
}
if resp.StatusCode() != http.StatusOK {
return nil, fmt.Errorf("Error fetching Customer Keys. Status: %d, Message: %s", resp.StatusCode(), (resp.Body))
}
cloudAccounts := resp.JSON200
result := make([]map[string]interface{}, 0, len(*cloudAccounts))
for _, account := range *cloudAccounts {
result = append(result, map[string]interface{}{
"organization_id" : account.OrganizationId,
"provider" : account.Provider,
"provider_id" : account.ProviderId,
})
}
return result, nil
}
Loading
Loading