diff --git a/docs/resources/secretstore.md b/docs/resources/secretstore.md
new file mode 100644
index 0000000..f86b98f
--- /dev/null
+++ b/docs/resources/secretstore.md
@@ -0,0 +1,133 @@
+---
+# generated by https://github.com/hashicorp/terraform-plugin-docs
+page_title: "humanitec_secretstore Resource - terraform-provider-humanitec"
+subcategory: ""
+description: |-
+ An external secret management system used by an organization to store secrets referenced in Humanitec.
+---
+
+# humanitec_secretstore (Resource)
+
+An external secret management system used by an organization to store secrets referenced in Humanitec.
+
+## Example Usage
+
+```terraform
+resource "humanitec_secretstore" "secret_store_gcpsm" {
+ id = "secretstore_id"
+ gcpsm = {
+ project_id = "example-project"
+ auth = {
+ secret_access_key = "secret-access-key"
+ }
+ }
+}
+```
+
+
+## Schema
+
+### Required
+
+- `id` (String) The ID of the Secret Store.
+
+### Optional
+
+- `awssm` (Attributes) AWS Secret Manager specification. (see [below for nested schema](#nestedatt--awssm))
+- `azurekv` (Attributes) Azure KV Secret Manager specification. (see [below for nested schema](#nestedatt--azurekv))
+- `gcpsm` (Attributes) GCP Secret Manager specification. (see [below for nested schema](#nestedatt--gcpsm))
+- `primary` (Boolean) Whether the Secret Store is the Primary one for the organization.
+- `vault` (Attributes) Vault specification. (see [below for nested schema](#nestedatt--vault))
+
+
+### Nested Schema for `awssm`
+
+Required:
+
+- `region` (String) The region of AWS Secret Manager.
+
+Optional:
+
+- `auth` (Attributes, Sensitive) Credentials to authenticate to AWS Secret Manager. (see [below for nested schema](#nestedatt--awssm--auth))
+
+
+### Nested Schema for `awssm.auth`
+
+Required:
+
+- `access_key_id` (String) The Access Key ID.
+- `secret_access_key` (String) The Secret Access Key.
+
+
+
+
+### Nested Schema for `azurekv`
+
+Required:
+
+- `tenant_id` (String) The AzureKV Tenant ID.
+- `url` (String) The AzureKV URL.
+
+Optional:
+
+- `auth` (Attributes, Sensitive) Credentials to authenticate to Azure Key Vault. (see [below for nested schema](#nestedatt--azurekv--auth))
+
+
+### Nested Schema for `azurekv.auth`
+
+Required:
+
+- `client_id` (String) The AzureKV Client ID.
+- `client_secret` (String) The AzureKV Client Secret.
+
+
+
+
+### Nested Schema for `gcpsm`
+
+Required:
+
+- `project_id` (String) The project ID of the GCPSM.
+
+Optional:
+
+- `auth` (Attributes, Sensitive) Credentials to authenticate the GCPSM. (see [below for nested schema](#nestedatt--gcpsm--auth))
+
+
+### Nested Schema for `gcpsm.auth`
+
+Required:
+
+- `secret_access_key` (String) The Secret Access Key.
+
+
+
+
+### Nested Schema for `vault`
+
+Required:
+
+- `url` (String) The Vault URL.
+
+Optional:
+
+- `agent_id` (String) Reference to the agent to use to hit Vault.
+- `auth` (Attributes, Sensitive) Credentials to authenticate the Vault. (see [below for nested schema](#nestedatt--vault--auth))
+- `path` (String) The path used to read / write secrets.
+
+
+### Nested Schema for `vault.auth`
+
+Optional:
+
+- `role` (String) Role to assume to access Vault.
+- `token` (String) Token to access Vault.
+
+## Import
+
+Import is supported using the following syntax:
+
+```shell
+# import an existing secret store
+terraform import humanitec_secretstore.secret_store_gcpsm secretstore_id
+```
diff --git a/examples/resources/humanitec_secretstore/import.sh b/examples/resources/humanitec_secretstore/import.sh
new file mode 100644
index 0000000..e89ce00
--- /dev/null
+++ b/examples/resources/humanitec_secretstore/import.sh
@@ -0,0 +1,3 @@
+# import an existing secret store
+terraform import humanitec_secretstore.secret_store_gcpsm secretstore_id
+
diff --git a/examples/resources/humanitec_secretstore/resource.tf b/examples/resources/humanitec_secretstore/resource.tf
new file mode 100644
index 0000000..1694317
--- /dev/null
+++ b/examples/resources/humanitec_secretstore/resource.tf
@@ -0,0 +1,9 @@
+resource "humanitec_secretstore" "secret_store_gcpsm" {
+ id = "secretstore_id"
+ gcpsm = {
+ project_id = "example-project"
+ auth = {
+ secret_access_key = "secret-access-key"
+ }
+ }
+}
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index 524ac47..166deb2 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -163,6 +163,7 @@ func (p *HumanitecProvider) Resources(ctx context.Context) []func() resource.Res
NewResourcePipeline,
NewResourceResourceDriver,
NewResourceRule,
+ NewResourceSecretStore,
NewResourceValue,
NewResourceWebhook,
}
diff --git a/internal/provider/resource_secret_store.go b/internal/provider/resource_secret_store.go
new file mode 100644
index 0000000..0ea86d3
--- /dev/null
+++ b/internal/provider/resource_secret_store.go
@@ -0,0 +1,469 @@
+package provider
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/hashicorp/terraform-plugin-framework/diag"
+ "github.com/hashicorp/terraform-plugin-framework/path"
+ "github.com/hashicorp/terraform-plugin-framework/resource"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+ "github.com/humanitec/humanitec-go-autogen"
+ "github.com/humanitec/humanitec-go-autogen/client"
+)
+
+// Ensure provider defined types fully satisfy framework interfaces
+var _ resource.Resource = &SecretStore{}
+var _ resource.ResourceWithImportState = &SecretStore{}
+
+func NewResourceSecretStore() resource.Resource {
+ return &SecretStore{}
+}
+
+// SecretStore defines the resource implementation.
+type SecretStore struct {
+ client *humanitec.Client
+ orgId string
+}
+
+// SecretStoreModel describes the app data model.
+type SecretStoreModel struct {
+ ID types.String `tfsdk:"id"`
+ Primary types.Bool `tfsdk:"primary"`
+ AwsSM *AwsSMModel `tfsdk:"awssm"`
+ AzureKV *AzureKVModel `tfsdk:"azurekv"`
+ GcpSM *GcpSMModel `tfsdk:"gcpsm"`
+ Vault *VaultModel `tfsdk:"vault"`
+}
+
+type AwsSMModel struct {
+ Auth *AwsAuthModel `tfsdk:"auth"`
+ Region types.String `tfsdk:"region"`
+}
+
+type AwsAuthModel struct {
+ AccessKeyID types.String `tfsdk:"access_key_id"`
+ SecretAccessKey types.String `tfsdk:"secret_access_key"`
+}
+
+type AzureKVModel struct {
+ Auth *AzureKVAuthModel `tfsdk:"auth"`
+ TenantID types.String `tfsdk:"tenant_id"`
+ Url types.String `tfsdk:"url"`
+}
+
+type AzureKVAuthModel struct {
+ ClientID types.String `tfsdk:"client_id"`
+ ClientSecret types.String `tfsdk:"client_secret"`
+}
+
+type GcpSMModel struct {
+ Auth *GcpAuthModel `tfsdk:"auth"`
+ ProjectID types.String `tfsdk:"project_id"`
+}
+
+type GcpAuthModel struct {
+ SecretAccessKey types.String `tfsdk:"secret_access_key"`
+}
+
+type VaultModel struct {
+ Auth *VaultAuthModel `tfsdk:"auth"`
+ AgentID types.String `tfsdk:"agent_id"`
+ Path types.String `tfsdk:"path"`
+ Url types.String `tfsdk:"url"`
+}
+
+type VaultAuthModel struct {
+ Role types.String `tfsdk:"role"`
+ Token types.String `tfsdk:"token"`
+}
+
+func (*SecretStore) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_secretstore"
+}
+
+func (*SecretStore) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ MarkdownDescription: "An external secret management system used by an organization to store secrets referenced in Humanitec.",
+
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ MarkdownDescription: "The ID of the Secret Store.",
+ Required: true,
+ },
+ "primary": schema.BoolAttribute{
+ MarkdownDescription: "Whether the Secret Store is the Primary one for the organization.",
+ Optional: true,
+ Computed: true,
+ Default: booldefault.StaticBool(false),
+ },
+ "awssm": schema.SingleNestedAttribute{
+ MarkdownDescription: "AWS Secret Manager specification.",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "region": schema.StringAttribute{
+ MarkdownDescription: "The region of AWS Secret Manager.",
+ Required: true,
+ },
+ "auth": schema.SingleNestedAttribute{
+ MarkdownDescription: "Credentials to authenticate to AWS Secret Manager.",
+ Sensitive: true,
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "access_key_id": schema.StringAttribute{
+ MarkdownDescription: "The Access Key ID.",
+ Required: true,
+ },
+ "secret_access_key": schema.StringAttribute{
+ MarkdownDescription: "The Secret Access Key.",
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ "azurekv": schema.SingleNestedAttribute{
+ MarkdownDescription: "Azure KV Secret Manager specification.",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "tenant_id": schema.StringAttribute{
+ MarkdownDescription: "The AzureKV Tenant ID.",
+ Required: true,
+ },
+ "url": schema.StringAttribute{
+ MarkdownDescription: "The AzureKV URL.",
+ Required: true,
+ },
+ "auth": schema.SingleNestedAttribute{
+ MarkdownDescription: "Credentials to authenticate to Azure Key Vault.",
+ Sensitive: true,
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "client_id": schema.StringAttribute{
+ MarkdownDescription: "The AzureKV Client ID.",
+ Required: true,
+ },
+ "client_secret": schema.StringAttribute{
+ MarkdownDescription: "The AzureKV Client Secret.",
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ "gcpsm": schema.SingleNestedAttribute{
+ MarkdownDescription: "GCP Secret Manager specification.",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "project_id": schema.StringAttribute{
+ MarkdownDescription: "The project ID of the GCPSM.",
+ Required: true,
+ },
+ "auth": schema.SingleNestedAttribute{
+ MarkdownDescription: "Credentials to authenticate the GCPSM.",
+ Sensitive: true,
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "secret_access_key": schema.StringAttribute{
+ MarkdownDescription: "The Secret Access Key.",
+ Required: true,
+ },
+ },
+ },
+ },
+ },
+ "vault": schema.SingleNestedAttribute{
+ MarkdownDescription: "Vault specification.",
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "url": schema.StringAttribute{
+ Required: true,
+ MarkdownDescription: "The Vault URL.",
+ },
+ "path": schema.StringAttribute{
+ MarkdownDescription: "The path used to read / write secrets.",
+ Optional: true,
+ },
+ "agent_id": schema.StringAttribute{
+ MarkdownDescription: "Reference to the agent to use to hit Vault.",
+ Optional: true,
+ },
+ "auth": schema.SingleNestedAttribute{
+ MarkdownDescription: "Credentials to authenticate the Vault.",
+ Sensitive: true,
+ Optional: true,
+ Attributes: map[string]schema.Attribute{
+ "token": schema.StringAttribute{
+ MarkdownDescription: "Token to access Vault.",
+ Optional: true,
+ },
+ "role": schema.StringAttribute{
+ MarkdownDescription: "Role to assume to access Vault.",
+ Optional: true,
+ },
+ },
+ },
+ },
+ },
+ },
+ }
+}
+
+func (s *SecretStore) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
+ // Prevent panic if the provider has not been configured.
+ if req.ProviderData == nil {
+ return
+ }
+
+ resdata, ok := req.ProviderData.(*HumanitecData)
+
+ if !ok {
+ resp.Diagnostics.AddError(
+ "Unexpected Resource Configure Type",
+ fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
+ )
+
+ return
+ }
+
+ s.client = resdata.Client
+ s.orgId = resdata.OrgID
+}
+
+func parseSecretStoreResponse(res *client.SecretStoreResponse, data *SecretStoreModel) {
+ data.ID = types.StringValue(res.Id)
+ data.Primary = types.BoolValue(res.Primary)
+ if res.Awssm != nil {
+ if data.AwsSM == nil {
+ data.AwsSM = &AwsSMModel{}
+ }
+ if res.Awssm.Region != nil {
+ data.AwsSM.Region = types.StringValue(*res.Awssm.Region)
+ }
+ } else if res.Azurekv != nil {
+ if data.AzureKV == nil {
+ data.AzureKV = &AzureKVModel{}
+ }
+ if res.Azurekv.TenantId != nil {
+ data.AzureKV.TenantID = types.StringValue(*res.Azurekv.TenantId)
+ }
+ if res.Azurekv.Url != nil {
+ data.AzureKV.Url = types.StringValue(*res.Azurekv.Url)
+ }
+ } else if res.Gcpsm != nil {
+ if data.GcpSM == nil {
+ data.GcpSM = &GcpSMModel{}
+ }
+ if res.Gcpsm.ProjectId != nil {
+ data.GcpSM.ProjectID = types.StringValue(*res.Gcpsm.ProjectId)
+ }
+ } else if res.Vault != nil {
+ if data.Vault == nil {
+ data.Vault = &VaultModel{}
+ }
+ if res.Vault.AgentId != nil {
+ data.Vault.AgentID = types.StringValue(*res.Vault.AgentId)
+ }
+ if res.Vault.Path != nil {
+ data.Vault.Path = types.StringValue(*res.Vault.Path)
+ }
+ if res.Vault.Url != nil {
+ data.Vault.Url = types.StringValue(*res.Vault.Url)
+ }
+ }
+}
+
+func toSecretStoreRequest(data *SecretStoreModel) (*client.CreateSecretStorePayloadRequest, diag.Diagnostics) {
+ diags := diag.Diagnostics{}
+ secretStorePayload := &client.CreateSecretStorePayloadRequest{
+ Id: data.ID.ValueString(),
+ Primary: data.Primary.ValueBool(),
+ }
+ if data.AwsSM != nil {
+ secretStorePayload.Awssm = &client.AWSSMRequest{
+ Region: data.AwsSM.Region.ValueStringPointer(),
+ }
+ if data.AwsSM.Auth != nil {
+ secretStorePayload.Awssm.Auth = &client.AWSAuthRequest{
+ AccessKeyId: data.AwsSM.Auth.AccessKeyID.ValueStringPointer(),
+ SecretAccessKey: data.AwsSM.Auth.SecretAccessKey.ValueStringPointer(),
+ }
+ }
+ } else if data.AzureKV != nil {
+ secretStorePayload.Azurekv = &client.AzureKVRequest{
+ TenantId: data.AzureKV.TenantID.ValueStringPointer(),
+ Url: data.AzureKV.Url.ValueStringPointer(),
+ }
+ if data.AzureKV.Auth != nil {
+ secretStorePayload.Azurekv.Auth = &client.AzureAuthRequest{
+ ClientId: data.AzureKV.Auth.ClientID.ValueStringPointer(),
+ ClientSecret: data.AzureKV.Auth.ClientSecret.ValueStringPointer(),
+ }
+ }
+ } else if data.GcpSM != nil {
+ secretStorePayload.Gcpsm = &client.GCPSMRequest{
+ ProjectId: data.GcpSM.ProjectID.ValueStringPointer(),
+ }
+ if data.GcpSM.Auth != nil {
+ secretStorePayload.Gcpsm.Auth = &client.GCPAuthRequest{
+ SecretAccessKey: data.GcpSM.Auth.SecretAccessKey.ValueStringPointer(),
+ }
+ }
+ } else if data.Vault != nil {
+ secretStorePayload.Vault = &client.VaultRequest{
+ AgentId: data.Vault.AgentID.ValueStringPointer(),
+ Url: data.Vault.Url.ValueStringPointer(),
+ Path: data.Vault.Path.ValueStringPointer(),
+ }
+ if data.Vault.Auth != nil {
+ secretStorePayload.Vault.Auth = &client.VaultAuthRequest{
+ Token: data.Vault.Auth.Token.ValueStringPointer(),
+ Role: data.Vault.Auth.Role.ValueStringPointer(),
+ }
+ }
+ }
+
+ return secretStorePayload, diags
+}
+
+func (s *SecretStore) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var data *SecretStoreModel
+
+ // Read Terraform plan data into the model
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ httpBody, diags := toSecretStoreRequest(data)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ httpResp, err := s.client.PostOrgsOrgIdSecretstoresWithResponse(ctx, s.orgId, *httpBody)
+ if err != nil {
+ resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to create secret role, got error: %s", err))
+ return
+ }
+
+ if httpResp.StatusCode() != 201 {
+ resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to create secret store, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body))
+ return
+ }
+
+ // Save data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+// Read implements resource.Resource.
+func (s *SecretStore) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var data *SecretStoreModel
+
+ // Read Terraform prior state data into the model
+ resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ id := data.ID.ValueString()
+
+ httpResp, err := s.client.GetOrgsOrgIdSecretstoresStoreIdWithResponse(ctx, s.orgId, id)
+ if err != nil {
+ resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to read secret store, got error: %s", err))
+ return
+ }
+ if httpResp.StatusCode() != 200 {
+ resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to read secret store, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body))
+ return
+ }
+
+ if httpResp.JSON200 == nil {
+ resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to read secret store, missing body, body: %s", httpResp.Body))
+ return
+ }
+
+ parseSecretStoreResponse(httpResp.JSON200, data)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+
+}
+
+func (s *SecretStore) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var data, state *SecretStoreModel
+
+ // Read Terraform plan data into the model
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+ resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ id := state.ID.ValueString()
+
+ createBody, diags := toSecretStoreRequest(data)
+ resp.Diagnostics.Append(diags...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ var updateBody client.UpdateSecretStorePayloadRequest
+ updateBody.Primary = &createBody.Primary
+ if createBody.Awssm != nil {
+ updateBody.Awssm = createBody.Awssm
+ } else if createBody.Azurekv != nil {
+ updateBody.Azurekv = createBody.Azurekv
+ } else if createBody.Gcpsm != nil {
+ updateBody.Gcpsm = createBody.Gcpsm
+ } else if createBody.Vault != nil {
+ updateBody.Vault = createBody.Vault
+ }
+
+ httpResp, err := s.client.PatchOrgsOrgIdSecretstoresStoreIdWithResponse(ctx, s.orgId, id, updateBody)
+ if err != nil {
+ resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to update secret store, got error: %s", err))
+ return
+ }
+
+ if httpResp.StatusCode() != 200 {
+ resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to update secret store, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body))
+ return
+ }
+
+ parseSecretStoreResponse(httpResp.JSON200, data)
+
+ // Save updated data into Terraform state
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (s *SecretStore) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var data *SecretStoreModel
+
+ // Read Terraform prior state data into the model
+ resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+
+ id := data.ID.ValueString()
+
+ httpResp, err := s.client.DeleteOrgsOrgIdSecretstoresStoreIdWithResponse(ctx, s.orgId, id)
+ if err != nil {
+ resp.Diagnostics.AddError(HUM_CLIENT_ERR, fmt.Sprintf("Unable to delete secret store, got error: %s", err))
+ return
+ }
+
+ if httpResp.StatusCode() != 204 {
+ resp.Diagnostics.AddError(HUM_API_ERR, fmt.Sprintf("Unable to delete secret store, unexpected status code: %d, body: %s", httpResp.StatusCode(), httpResp.Body))
+ return
+ }
+}
+
+func (s *SecretStore) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+}
diff --git a/internal/provider/resource_secret_store_test.go b/internal/provider/resource_secret_store_test.go
new file mode 100644
index 0000000..e1c2627
--- /dev/null
+++ b/internal/provider/resource_secret_store_test.go
@@ -0,0 +1,283 @@
+package provider
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
+ "github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
+)
+
+func TestAccResourceSecretStore_AzureKV(t *testing.T) {
+ id := fmt.Sprintf("azurekv-test-%d", time.Now().UnixNano())
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: testAccSecretStoreAzureKV(id, "tenant-id", "azurekv-url", "client-id", "client-secret"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "primary", "false"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "azurekv.tenant_id", "tenant-id"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "azurekv.url", "azurekv-url"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "azurekv.auth.client_id", "client-id"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "humanitec_secretstore.secret_store_azurekv_test",
+ ImportState: true,
+ ImportStateIdFunc: func(s *terraform.State) (string, error) {
+ return id, nil
+ },
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"azurekv.auth"},
+ },
+ // Update and Read testing
+ {
+ Config: testAccSecretStoreAzureKV(id, "tenant-id", "azurekv-url-changed", "client-id-changed", "client-secret"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "primary", "false"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "azurekv.tenant_id", "tenant-id"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "azurekv.url", "azurekv-url-changed"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_azurekv_test", "azurekv.auth.client_id", "client-id-changed"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccResourceSecretStore_Aws(t *testing.T) {
+ id := fmt.Sprintf("awssm-test-%d", time.Now().UnixNano())
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: testAccSecretStoreAwsSM(id, "access-key-id", "secret-access-key"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_awssm_test", "primary", "true"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_awssm_test", "awssm.region", "eu-central-1"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_awssm_test", "awssm.auth.access_key_id", "access-key-id"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "humanitec_secretstore.secret_store_awssm_test",
+ ImportState: true,
+ ImportStateIdFunc: func(s *terraform.State) (string, error) {
+ return id, nil
+ },
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"awssm.auth"},
+ },
+ // Update and Read testing
+ {
+ Config: testAccSecretStoreAwsSM(id, "access-key-id-changed", "secret-access-key"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_awssm_test", "primary", "true"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_awssm_test", "awssm.region", "eu-central-1"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_awssm_test", "awssm.auth.access_key_id", "access-key-id-changed"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccResourceSecretStore_GcpSM(t *testing.T) {
+ id := fmt.Sprintf("gcpsm-test-%d", time.Now().UnixNano())
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: testAccSecretStoreGcpSM(id, "gcp-project", "secret-access-key"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_gcpsm_test", "gcpsm.project_id", "gcp-project"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_gcpsm_test", "gcpsm.auth.secret_access_key", "secret-access-key"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "humanitec_secretstore.secret_store_gcpsm_test",
+ ImportState: true,
+ ImportStateIdFunc: func(s *terraform.State) (string, error) {
+ return id, nil
+ },
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"gcpsm.auth"},
+ },
+ // Update and Read testing
+ {
+ Config: testAccSecretStoreGcpSM(id, "gcp-project-changed", "secret-access-key-changed"),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_gcpsm_test", "gcpsm.project_id", "gcp-project-changed"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_gcpsm_test", "gcpsm.auth.secret_access_key", "secret-access-key-changed"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccResourceSecretStore_Vault(t *testing.T) {
+ id := fmt.Sprintf("vault-test-%d", time.Now().UnixNano())
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: testAccSecretStoreVault(id, "vault-url", "vault-token", false),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "primary", "false"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.url", "vault-url"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.auth.token", "vault-token"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "humanitec_secretstore.secret_store_vault_test",
+ ImportState: true,
+ ImportStateIdFunc: func(s *terraform.State) (string, error) {
+ return id, nil
+ },
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"vault.auth"},
+ },
+ // Update and Read testing
+ {
+ Config: testAccSecretStoreVault(id, "vault-url-changed", "vault-token-changed", true),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "primary", "true"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.url", "vault-url-changed"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.auth.token", "vault-token-changed"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func TestAccResourceSecretStore_Vault_RemoveAuth(t *testing.T) {
+ id := fmt.Sprintf("vault-test-%d", time.Now().UnixNano())
+
+ resource.Test(t, resource.TestCase{
+ PreCheck: func() { testAccPreCheck(t) },
+ ProtoV6ProviderFactories: testAccProtoV6ProviderFactories,
+ Steps: []resource.TestStep{
+ // Create and Read testing
+ {
+ Config: testAccSecretStoreVault(id, "vault-url", "vault-token", false),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "primary", "false"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.url", "vault-url"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.auth.token", "vault-token"),
+ ),
+ },
+ // ImportState testing
+ {
+ ResourceName: "humanitec_secretstore.secret_store_vault_test",
+ ImportState: true,
+ ImportStateIdFunc: func(s *terraform.State) (string, error) {
+ return id, nil
+ },
+ ImportStateVerify: true,
+ ImportStateVerifyIgnore: []string{"vault.auth"},
+ },
+ // Update and Read testing
+ {
+ Config: testAccSecretStoreVaultNoAuth(id, "vault-url", false),
+ Check: resource.ComposeAggregateTestCheckFunc(
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "primary", "false"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.url", "vault-url"),
+ resource.TestCheckResourceAttr("humanitec_secretstore.secret_store_vault_test", "vault.auth.%", "0"),
+ ),
+ },
+ // Delete testing automatically occurs in TestCase
+ },
+ })
+}
+
+func testAccSecretStoreAzureKV(storeID, tenantID, url, clientID, clientSecret string) string {
+ return fmt.Sprintf(`
+ resource "humanitec_secretstore" "secret_store_azurekv_test" {
+ id = "%s"
+ azurekv = {
+ tenant_id = "%s"
+ url = "%s"
+ auth = {
+ client_id = "%s"
+ client_secret = "%s"
+ }
+ }
+ }
+`, storeID, tenantID, url, clientID, clientSecret)
+}
+
+func testAccSecretStoreAwsSM(storeID, accessKeyID, secretAccessKey string) string {
+ return fmt.Sprintf(`
+ resource "humanitec_secretstore" "secret_store_awssm_test" {
+ id = "%s"
+ primary = true
+ awssm = {
+ region = "eu-central-1"
+ auth = {
+ access_key_id = "%s"
+ secret_access_key = "%s"
+ }
+ }
+ }
+`, storeID, accessKeyID, secretAccessKey)
+}
+
+func testAccSecretStoreGcpSM(storeID, projectID, secretAccessKey string) string {
+ return fmt.Sprintf(`
+ resource "humanitec_secretstore" "secret_store_gcpsm_test" {
+ id = "%s"
+ gcpsm = {
+ project_id = "%s"
+ auth = {
+ secret_access_key = "%s"
+ }
+ }
+ }
+`, storeID, projectID, secretAccessKey)
+}
+
+func testAccSecretStoreVault(storeID, url, token string, primary bool) string {
+ return fmt.Sprintf(`
+ resource "humanitec_secretstore" "secret_store_vault_test" {
+ id = "%s"
+ primary = %v
+ vault = {
+ url = "%s"
+ auth = {
+ token = "%s"
+ }
+ }
+ }
+`, storeID, primary, url, token)
+}
+
+func testAccSecretStoreVaultNoAuth(storeID, url string, primary bool) string {
+ return fmt.Sprintf(`
+ resource "humanitec_secretstore" "secret_store_vault_test" {
+ id = "%s"
+ primary = %v
+ vault = {
+ url = "%s"
+ }
+ }
+`, storeID, primary, url)
+}