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

support plugin tencent cloud #2334

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
111 changes: 111 additions & 0 deletions vault/data_source_tencentcloud_access_credentials.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package vault

import (
"fmt"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"log"

"github.com/hashicorp/terraform-provider-vault/internal/consts"
"github.com/hashicorp/terraform-provider-vault/internal/provider"
)

func tencentCloudAccessCredentialsDataSource() *schema.Resource {
return &schema.Resource{
Read: provider.ReadWrapper(tencentCloudAccessCredentialsDataSourceRead),

Schema: map[string]*schema.Schema{
"backend": {
Type: schema.TypeString,
Required: true,
Description: "Tencent cloud Secret Backend to read credentials from.",
},

"role": {
Type: schema.TypeString,
Required: true,
Description: "Tencent cloud Secret Role to read credentials from.",
},

"secret_id": {
Type: schema.TypeString,
Computed: true,
Description: "Tencent cloud secret ID read from Vault.",
},

"secret_key": {
Type: schema.TypeString,
Computed: true,
Description: "Tencent cloud secret key read from Vault.",
},

"token": {
Type: schema.TypeString,
Computed: true,
Description: "Tencent cloud security token read from Vault. (Only returned if type is 'sts').",
},

consts.FieldLeaseID: {
Type: schema.TypeString,
Computed: true,
Description: "Lease identifier assigned by vault.",
},

consts.FieldLeaseDuration: {
Type: schema.TypeInt,
Computed: true,
Description: "Lease duration in seconds relative to the time in lease_start_time.",
},

consts.FieldLeaseRenewable: {
Type: schema.TypeBool,
Computed: true,
Description: "True if the duration of this lease can be extended through renewal.",
},
},
}
}

func tencentCloudAccessCredentialsDataSourceRead(d *schema.ResourceData, meta interface{}) error {
client, e := provider.GetClient(d, meta)
if e != nil {
return e
}

backend := d.Get("backend").(string)
credType := "creds"
role := d.Get("role").(string)
path := backend + "/" + credType + "/" + role

data := map[string][]string{}

log.Printf("[DEBUG] Reading %q from Vault with data %#v", path, data)
secret, err := client.Logical().ReadWithData(path, data)
if err != nil {
return fmt.Errorf("error reading from Vault: %s", err)
}
log.Printf("[DEBUG] Read %q from Vault", path)

if secret == nil {
return fmt.Errorf("no role found at path %q", path)
}

secretId := secret.Data["secret_id"].(string)
secretKey := secret.Data["secret_key"].(string)
var token string
if secret.Data["token"] != nil {
token = secret.Data["token"].(string)
}

d.SetId(secret.LeaseID)
_ = d.Set("secret_id", secretId)
_ = d.Set("secret_key", secretKey)
_ = d.Set("token", token)
_ = d.Set(consts.FieldLeaseID, secret.LeaseID)
_ = d.Set(consts.FieldLeaseDuration, secret.LeaseDuration)
_ = d.Set(consts.FieldLeaseRenewable, secret.Renewable)

return nil
}
20 changes: 20 additions & 0 deletions vault/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ var (
Resource: UpdateSchemaResource(nomadAccessCredentialsDataSource()),
PathInventory: []string{"/nomad/creds/{role}"},
},
"vault_tencentcloud_access_credentials": {
Resource: UpdateSchemaResource(tencentCloudAccessCredentialsDataSource()),
PathInventory: []string{"/tencentcloud/creds/{role}"},
},
"vault_aws_access_credentials": {
Resource: UpdateSchemaResource(awsAccessCredentialsDataSource()),
PathInventory: []string{"/aws/creds"},
Expand Down Expand Up @@ -285,6 +289,22 @@ var (
Resource: UpdateSchemaResource(awsSecretBackendResource()),
PathInventory: []string{"/aws/config/root"},
},
"vault_tencentcloud_auth_backend_client": {
Resource: UpdateSchemaResource(tencentCloudAuthBackendClientResource()),
PathInventory: []string{"/auth/tencentcloud/config/client"},
},
"vault_tencentcloud_auth_backend_role": {
Resource: UpdateSchemaResource(tencentCloudAuthBackendRoleResource()),
PathInventory: []string{"/auth/tencentcloud/role/{role}"},
},
"vault_tencentcloud_secret_backend": {
Resource: UpdateSchemaResource(tencentCloudSecretBackendResource()),
PathInventory: []string{"/tencentcloud/config"},
},
"vault_tencentcloud_secret_backend_role": {
Resource: UpdateSchemaResource(tencentCloudSecretBackendRoleResource("vault_tencentcloud_secret_backend_role")),
PathInventory: []string{"/tencentcloud/role/{name}"},
},
"vault_aws_secret_backend_role": {
Resource: UpdateSchemaResource(awsSecretBackendRoleResource("vault_aws_secret_backend_role")),
PathInventory: []string{"/aws/roles/{name}"},
Expand Down
146 changes: 146 additions & 0 deletions vault/resource_tencentcloud_auth_backend_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package vault

import (
"context"
"log"
"regexp"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

"github.com/hashicorp/terraform-provider-vault/internal/consts"
"github.com/hashicorp/terraform-provider-vault/internal/provider"
)

func tencentCloudAuthBackendClientResource() *schema.Resource {
return &schema.Resource{
CreateContext: tencentCloudAuthBackendWrite,
ReadContext: provider.ReadContextWrapper(tencentCloudAuthBackendRead),
UpdateContext: tencentCloudAuthBackendWrite,
DeleteContext: tencentCloudAuthBackendDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},

Schema: map[string]*schema.Schema{
consts.FieldBackend: {
Type: schema.TypeString,
Optional: true,
Description: "Unique name of the auth backend to configure.",
ForceNew: true,
Default: "tencentcloud",
// standardise on no beginning or trailing slashes
StateFunc: func(v interface{}) string {
return strings.Trim(v.(string), "/")
},
},
consts.FieldSecretID: {
Type: schema.TypeString,
Optional: true,
Description: "Tencent Cloud Secret ID with permissions to query tencent cloud APIs.",
Sensitive: true,
},
consts.FieldSecretKey: {
Type: schema.TypeString,
Optional: true,
Description: "Tencent Cloud Secret key with permissions to query tencent cloud APIs.",
Sensitive: true,
},
},
}
}

func tencentCloudAuthBackendWrite(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, e := provider.GetClient(d, meta)
if e != nil {
return diag.FromErr(e)
}

// if backend comes from the config, it won't have the StateFunc
// applied yet, so we need to apply it again.
backend := d.Get(consts.FieldBackend).(string)
path := tencentCloudAuthBackendClientPath(backend)

data := map[string]interface{}{}

if d.HasChange(consts.FieldSecretID) || d.HasChange(consts.FieldSecretKey) {
log.Printf("[DEBUG] Updating Tencent Cloud credentials at %q", path)
data[consts.FieldSecretID] = d.Get(consts.FieldSecretID).(string)
data[consts.FieldSecretKey] = d.Get(consts.FieldSecretKey).(string)
}

log.Printf("[DEBUG] Writing Tencent Cloud auth backend client config to %q", path)
_, err := client.Logical().WriteWithContext(ctx, path, data)
if err != nil {
return diag.Errorf("error writing to %q: %s", path, err)
}
log.Printf("[DEBUG] Wrote tencent cloud auth backend client config to %q", path)

d.SetId(path)

return tencentCloudAuthBackendRead(ctx, d, meta)
}

func tencentCloudAuthBackendRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, e := provider.GetClient(d, meta)
if e != nil {
return diag.FromErr(e)
}

log.Printf("[DEBUG] Reading Tencent Cloud auth backend client config")
secret, err := client.Logical().ReadWithContext(ctx, d.Id())
if err != nil {
return diag.Errorf("error reading Tencent Cloud auth backend client config from %q: %s", d.Id(), err)
}
log.Printf("[DEBUG] Read Tencent Cloud auth backend client config")

if secret == nil {
log.Printf("[WARN] No info found at %q; removing from state.", d.Id())
d.SetId("")
return nil
}

// set the backend to the original passed path (without config/client at the end)
re := regexp.MustCompile(`^auth/(.*)/config/client$`)
if !re.MatchString(d.Id()) {
return diag.Errorf("`config/client` has not been appended to the ID (%s)", d.Id())
}
_ = d.Set("backend", re.FindStringSubmatch(d.Id())[1])

fields := []string{
consts.FieldSecretID,
consts.FieldSecretKey,
}
for _, k := range fields {
if v, ok := secret.Data[k]; ok {
if err := d.Set(k, v); err != nil {
return diag.FromErr(err)
}
}
}
return nil
}

func tencentCloudAuthBackendDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
client, e := provider.GetClient(d, meta)
if e != nil {
return diag.FromErr(e)
}

log.Printf("[DEBUG] Deleting Tencent Cloud auth backend client config from %q", d.Id())
_, err := client.Logical().DeleteWithContext(ctx, d.Id())
if err != nil {
return diag.Errorf("error deleting Tencent Cloud auth backend client config from %q: %s", d.Id(), err)
}
log.Printf("[DEBUG] Deleted Tencent Cloud auth backend client config from %q", d.Id())

return nil
}

func tencentCloudAuthBackendClientPath(path string) string {
return "auth/" + strings.Trim(path, "/") + "/config/client"
}
Loading
Loading