Add credential library resource for Vault (#114)

* Integrate with Vault to retrieve and manage per session credentials

Co-authored-by: Louis Ruch <louisruch@gmail.com>
This commit is contained in:
Jeff MalnickandLouis Ruch authored and GitHub committed 2021-06-22 21:07:07 -07:00
1 parent 7c73927d17
commit 4f0509c55d
20 files changed
+1433 -99

No files matched your search

@@ -0,0 +1,86 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "boundary_credential_library_vault Resource - terraform-provider-boundary"
subcategory: ""
description: |-
The credential library for Vault resource allows you to configure a Boundary credential library for Vault.
---
# boundary_credential_library_vault (Resource)
The credential library for Vault resource allows you to configure a Boundary credential library for Vault.
## Example Usage
```terraform
resource "boundary_scope" "org" {
name = "organization_one"
description = "My first 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_vault" "foo" {
name = "foo"
description = "My first Vault credential store!"
address = "127.0.0.1"
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5"
scope_id = boundary_scope.project.id
}
resource "boundary_credential_library_vault" "foo" {
name = "foo"
description = "My first Vault credential library!"
credential_store_id = boundary_credential_store_vault.foo.id
path = "my/secret/foo"
http_method = "GET"
}
resource "boundary_credential_library_vault" "bar" {
name = "bar"
description = "My second Vault credential library!"
credential_store_id = boundary_credential_store_vault.foo.id
path = "my/secret/bar"
http_method = "POST"
request_body = <<EOT
{
"key": "Value",
}
EOT
}
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- **credential_store_id** (String) The ID of the credential store that this library belongs to.
- **path** (String) The Vault path to query
### Optional
- **description** (String) The Vault credential library description.
- **http_method** (String) The HTTP method to use when contacting Vault
- **http_request_body** (String) The raw string to use in HTTP request to Vault
- **name** (String) The Vault credential library name. Defaults to the resource name.
### Read-Only
- **id** (String) The ID of the Vault credential library.
## Import
Import is supported using the following syntax:
```shell
terraform import boundary_credential_library_vault.foo <my-id>
```
+72
View File
@@ -0,0 +1,72 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "boundary_credential_store_vault Resource - terraform-provider-boundary"
subcategory: ""
description: |-
The credential store for Vault resource allows you to configure a Boundary credential store for Vault.
---
# boundary_credential_store_vault (Resource)
The credential store for Vault resource allows you to configure a Boundary credential store for Vault.
## Example Usage
```terraform
resource "boundary_scope" "org" {
name = "organization_one"
description = "My first 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_vault" "example" {
name = "foo"
description = "My first Vault credential store!"
address = "127.0.0.1"
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5"
scope_id = boundary_scope.project.id
}
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- **address** (String) The address to Vault server
- **scope_id** (String) The scope for this credential store
- **token** (String, Sensitive) The Vault token
### Optional
- **ca_cert** (String) The Vault CA certificate to use
- **client_certificate** (String) The Vault client certificate
- **client_certificate_key** (String, Sensitive) The Vault client certificate key
- **description** (String) The Vault credential store description.
- **name** (String) The Vault credential store name. Defaults to the resource name.
- **namespace** (String) The namespace within Vault to use
- **tls_server_name** (String) The Vault TLS server name
- **tls_skip_verify** (Boolean) Whether or not to skip TLS verification
### Read-Only
- **client_certificate_key_hmac** (String) The Vault client certificate key hmac
- **id** (String) The ID of the Vault credential store.
- **token_hmac** (String) The Vault token hmac
## Import
Import is supported using the following syntax:
```shell
terraform import boundary_credential_store_vault.foo <my-id>
```
+20
View File
@@ -33,6 +33,22 @@ resource "boundary_scope" "project" {
auto_create_admin_role = true
}
resource "boundary_credential_store_vault" "foo" {
name = "vault_store"
description = "My first Vault credential store!"
address = "http://localhost:55001"
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5"
scope_id = boundary_scope.project.id
}
resource "boundary_credential_library_vault" "foo" {
name = "vault_library"
description = "My first Vault credential library!"
credential_store_id = boundary_credential_store_vault.foo.id
path = "database/creds/opened"
http_method = "GET"
}
resource "boundary_host_catalog" "foo" {
name = "test"
description = "test catalog"
@@ -72,6 +88,9 @@ resource "boundary_target" "foo" {
host_set_ids = [
boundary_host_set.foo.id
]
credential_library_ids = [
boundary_credential_library_vault.foo.id
]
}
```
@@ -85,6 +104,7 @@ resource "boundary_target" "foo" {
### Optional
- **credential_library_ids** (Set of String) A list of credential library ID's.
- **default_port** (Number) The default port for this target.
- **description** (String) The target description.
- **host_set_ids** (Set of String) A list of host set ID's.
@@ -0,0 +1 @@
terraform import boundary_credential_library_vault.foo <my-id>
@@ -0,0 +1,43 @@
resource "boundary_scope" "org" {
name = "organization_one"
description = "My first 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_vault" "foo" {
name = "foo"
description = "My first Vault credential store!"
address = "127.0.0.1"
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5"
scope_id = boundary_scope.project.id
}
resource "boundary_credential_library_vault" "foo" {
name = "foo"
description = "My first Vault credential library!"
credential_store_id = boundary_credential_store_vault.foo.id
path = "my/secret/foo"
http_method = "GET"
}
resource "boundary_credential_library_vault" "bar" {
name = "bar"
description = "My second Vault credential library!"
credential_store_id = boundary_credential_store_vault.foo.id
path = "my/secret/bar"
http_method = "POST"
request_body = <<EOT
{
"key": "Value",
}
EOT
}
@@ -0,0 +1 @@
terraform import boundary_credential_store_vault.foo <my-id>
@@ -0,0 +1,22 @@
resource "boundary_scope" "org" {
name = "organization_one"
description = "My first 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_vault" "example" {
name = "foo"
description = "My first Vault credential store!"
address = "127.0.0.1"
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5"
scope_id = boundary_scope.project.id
}
@@ -18,6 +18,22 @@ resource "boundary_scope" "project" {
auto_create_admin_role = true
}
resource "boundary_credential_store_vault" "foo" {
name = "vault_store"
description = "My first Vault credential store!"
address = "http://localhost:55001"
token = "s.0ufRo6XEGU2jOqnIr7OlFYP5"
scope_id = boundary_scope.project.id
}
resource "boundary_credential_library_vault" "foo" {
name = "vault_library"
description = "My first Vault credential library!"
credential_store_id = boundary_credential_store_vault.foo.id
path = "database/creds/opened"
http_method = "GET"
}
resource "boundary_host_catalog" "foo" {
name = "test"
description = "test catalog"
@@ -57,4 +73,7 @@ resource "boundary_target" "foo" {
host_set_ids = [
boundary_host_set.foo.id
]
credential_library_ids = [
boundary_credential_library_vault.foo.id
]
}
+6 -9
View File
@@ -13,17 +13,15 @@ require (
github.com/agext/levenshtein v1.2.3 // indirect
github.com/aliyun/alibaba-cloud-sdk-go v1.61.545 // indirect
github.com/aws/aws-sdk-go v1.35.4 // indirect
github.com/cenkalti/backoff/v3 v3.2.2 // indirect
github.com/circonus-labs/circonusllhist v0.1.4 // indirect
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe // indirect
github.com/coreos/go-oidc v2.2.1+incompatible // indirect
github.com/golang/snappy v0.0.2 // indirect
github.com/hashicorp/boundary v0.2.2
github.com/hashicorp/boundary/api v0.0.10
github.com/hashicorp/boundary/sdk v0.0.4
github.com/hashicorp/cap v0.0.0-20210518163718-e72205e8eaae
github.com/hashicorp/boundary v0.3.1-0.20210623022626-df35699c4ef2
github.com/hashicorp/boundary/api v0.0.12-0.20210623022626-df35699c4ef2
github.com/hashicorp/boundary/sdk v0.0.5-0.20210623022626-df35699c4ef2
github.com/hashicorp/cap v0.1.0
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
github.com/hashicorp/go-kms-wrapping v0.6.1
github.com/hashicorp/go-kms-wrapping v0.6.2
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/hashicorp/hcl/v2 v2.6.0 // indirect
github.com/hashicorp/terraform-plugin-docs v0.4.0
@@ -33,11 +31,10 @@ require (
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/oklog/run v1.1.0 // indirect
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac // indirect
github.com/prometheus/common v0.14.0 // indirect
github.com/prometheus/procfs v0.2.0 // indirect
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c // indirect
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
+42 -56
View File
@@ -158,10 +158,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs=
github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.4/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.6 h1:x/tmtOF9cDBoXH7XoAGOz2qqm1DknFD1590XmD/DUJ8=
github.com/armon/go-metrics v0.3.6/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.8 h1:oOxq3KPj0WhCuy50EhzwiyMyG2ovRQZpZLXQuOh2a/M=
github.com/armon/go-metrics v0.3.8/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18=
github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
@@ -198,8 +196,6 @@ github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M=
github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs=
github.com/cenkalti/backoff/v4 v4.0.2/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg=
github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc=
github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
@@ -246,8 +242,6 @@ github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDG
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-oidc/v3 v3.0.0 h1:/mAA0XMgYJw2Uqm7WKGCsKnjitE/+A0FFbOmiRJm7LQ=
github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -261,6 +255,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/danieljoos/wincred v1.0.2/go.mod h1:SnuYRW9lp1oJrZX/dXJqr0cPK5gYXqx3EJbmjhLdK9U=
@@ -310,10 +305,9 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DP
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.11.0 h1:l4iX0RqNnx/pU7rY2DB/I+znuYY0K3x6Ywac6EIr0PA=
github.com/fatih/color v1.11.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc=
github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/favadi/protoc-go-inject-tag v1.1.0/go.mod h1:13goAxKedbu5IbfI0n2wIKh1CCgZOwPNZQd0igDWvko=
@@ -364,8 +358,9 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
@@ -441,8 +436,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-metrics-stackdriver v0.2.0 h1:rbs2sxHAPn2OtUj9JdR/Gij1YKGl0BTVD0augB+HEjE=
github.com/google/go-metrics-stackdriver v0.2.0/go.mod h1:KLcPyp3dWJAFD+yHisGlJSZktIsTjb50eB72U2YZ9K0=
@@ -490,18 +486,16 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0 h1:IvO4FbbQL6n3v3M1rQNobZ61SGL0gJLdvKA5KETM7Xs=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0/go.mod h1:d2gYTOTUQklu06xp0AJYYmRdTVU1VKrqhkYfYag2L08=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/hashicorp/boundary v0.2.1 h1:I4O1BrqR1R6O449k1b7FGCOFXwgRKxhZoK8CltvsBoo=
github.com/hashicorp/boundary v0.2.1/go.mod h1:FwX0UmYaj3OFlKrhhaMcT8FvEZk/y/1AnZgxsk4xQQM=
github.com/hashicorp/boundary v0.2.2 h1:Gel7cjlcild1AZGVfR+4d28MmqnTQ6F/CTOAyEAFyis=
github.com/hashicorp/boundary v0.2.2/go.mod h1:Gd+jRjPuPqFHZLlA7+llzK4BlHxilp37cJDp7xswAGU=
github.com/hashicorp/boundary/api v0.0.10 h1:WdKR5dZ7FvAW0QG05jyKWt9ESu1vT/4E2LIDiSVJ1ZI=
github.com/hashicorp/boundary/api v0.0.10/go.mod h1:mZfLjpD0hU2YMopuobjh+ZmWMRLl9sooiPr46gi64i4=
github.com/hashicorp/boundary/sdk v0.0.4 h1:l3uuXOL5ZQwYc63Bm8sLY36XGUlIN/4Q2r2SqkmGTyw=
github.com/hashicorp/boundary v0.3.1-0.20210623022626-df35699c4ef2 h1:hJ8qTqevchi/REQy7JEDS1phXlAWs+2j1Kl8b3XfCiI=
github.com/hashicorp/boundary v0.3.1-0.20210623022626-df35699c4ef2/go.mod h1:wTfjDEGdal4/942BfnJ5yXDjB+LFhsrYY0aah4Q6FOk=
github.com/hashicorp/boundary/api v0.0.11/go.mod h1:mZfLjpD0hU2YMopuobjh+ZmWMRLl9sooiPr46gi64i4=
github.com/hashicorp/boundary/api v0.0.12-0.20210623022626-df35699c4ef2 h1:UTlcgB8eCeyPX7HrsmyNmsBHTuLM9/ZNgwvEMYgrd2s=
github.com/hashicorp/boundary/api v0.0.12-0.20210623022626-df35699c4ef2/go.mod h1:mZfLjpD0hU2YMopuobjh+ZmWMRLl9sooiPr46gi64i4=
github.com/hashicorp/boundary/sdk v0.0.4/go.mod h1:MQ8FJhseJrKpwvFDTn+AUAcJ1vdk1NKUxk7DxQgH7oQ=
github.com/hashicorp/cap v0.0.0-20210408110729-0dd65efe5473 h1:qEikB8/ychrgsll9feuGjVLt0qo5oktfyTWi7BLsUrg=
github.com/hashicorp/cap v0.0.0-20210408110729-0dd65efe5473/go.mod h1:hjMYKmFvk9AOL69NbqrahCHoMPZHRWqvRcdr7ciPU7g=
github.com/hashicorp/cap v0.0.0-20210518163718-e72205e8eaae h1:8tmylghjLoNNQdJdDddF54L38LakfoC/YfxJ7dGsAIE=
github.com/hashicorp/cap v0.0.0-20210518163718-e72205e8eaae/go.mod h1:VfBvK2ULRyqsuqAnjgZl7HJ7/CGMC7ro4H5eXiZuun8=
github.com/hashicorp/boundary/sdk v0.0.5-0.20210623022626-df35699c4ef2 h1:CPkNe8ipxlewl9UJ8GABAEBzm2ira5F9B8VK7CpkBTI=
github.com/hashicorp/boundary/sdk v0.0.5-0.20210623022626-df35699c4ef2/go.mod h1:MQ8FJhseJrKpwvFDTn+AUAcJ1vdk1NKUxk7DxQgH7oQ=
github.com/hashicorp/cap v0.1.0 h1:uBDfu9NDvmotza/mJW6vtQId+VYid9ztlTnDCW6YUWU=
github.com/hashicorp/cap v0.1.0/go.mod h1:VfBvK2ULRyqsuqAnjgZl7HJ7/CGMC7ro4H5eXiZuun8=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
@@ -511,8 +505,9 @@ github.com/hashicorp/dbassert v0.0.0-20200930125617-6218396928df/go.mod h1:+B5eZ
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-bexpr v0.1.7 h1:z48qzCgJkvdnMO/LDy3XHNyCyxnHiFGx9uTKLv0jW2Y=
github.com/hashicorp/go-bexpr v0.1.7/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/eventlogger v0.0.0-20210523164657-c216620e1746/go.mod h1:LG0lqGlYKC9FD5m5Umh7FW8SeJlciNUZv400J4+j094=
github.com/hashicorp/go-bexpr v0.1.8 h1:ETfuLF1bBAuHW/Qg6l1xCdV8WJ7lfatLtJ1N1w0IsfE=
github.com/hashicorp/go-bexpr v0.1.8/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU=
github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@@ -531,8 +526,6 @@ github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39
github.com/hashicorp/go-hclog v0.13.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.15.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.0 h1:uCeOEwSWGMwhJUdpUjk+1cVKIEfGu2/1nFXukimi2MU=
github.com/hashicorp/go-hclog v0.16.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o=
github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@@ -540,8 +533,9 @@ github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh
github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE=
github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-kms-wrapping v0.5.12/go.mod h1:yVIWtGOTh/cdGc++/NOlXLus0hJ19Lz4iFrpF6WsZh4=
github.com/hashicorp/go-kms-wrapping v0.6.1 h1:QwG2nGi3BXa8xpU5BRWKY5z6Xg1aqAErC9tAvDfMA3Y=
github.com/hashicorp/go-kms-wrapping v0.6.1/go.mod h1:lxD7e9q7ZyCtDEP+tnMevsEvw3M0gmZnneAgv8BaO1Q=
github.com/hashicorp/go-kms-wrapping v0.6.2 h1:ryj5jVvecszFG4yL4/0jQxGK6g1LCNVLWRH8ZXjrYbY=
github.com/hashicorp/go-kms-wrapping v0.6.2/go.mod h1:aUzqzg9WEm5mEcQcNI431QLmxKzGL80cvwGQyVSP15Y=
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
@@ -555,7 +549,6 @@ github.com/hashicorp/go-plugin v1.4.0/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ3
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY=
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs=
github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
github.com/hashicorp/go-retryablehttp v0.7.0 h1:eu1EI/mbirUgP5C8hVsTNaGZreBDlYiwC1FZWkvQPQ4=
github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
@@ -596,8 +589,8 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/shared-secure-libs v0.0.4/go.mod h1:xhtA0FH6AYYFOy0sir7u0O0zzdLi7ofU6oWxy+gjnuc=
github.com/hashicorp/shared-secure-libs v0.0.5 h1:qHd+wxqgvW+INIMU0uzF/Sw3+iaqAOk5SrcXzsThlvY=
github.com/hashicorp/shared-secure-libs v0.0.5/go.mod h1:xhtA0FH6AYYFOy0sir7u0O0zzdLi7ofU6oWxy+gjnuc=
github.com/hashicorp/shared-secure-libs v0.0.6 h1:QH22a9VbBP3b7v/e5In7uHTanimGPzq4oj0QHtVHhWI=
github.com/hashicorp/shared-secure-libs v0.0.6/go.mod h1:PH51kNtHA6kYV5Z8E3TOJM634iyp7IIxAMfLh0Dp35o=
github.com/hashicorp/terraform-exec v0.12.0/go.mod h1:SGhto91bVRlgXQWcJ5znSz+29UZIa8kpBbkGwQ+g9E8=
github.com/hashicorp/terraform-exec v0.13.3 h1:R6L2mNpDGSEqtLrSONN8Xth0xYwNrnEVzDz6LF/oJPk=
github.com/hashicorp/terraform-exec v0.13.3/go.mod h1:SSg6lbUsVB3DmFyCPjBPklqf6EYGX0TlQ6QTxOlikDU=
@@ -612,8 +605,9 @@ github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1 h1:OZ+Q7irJBDhb71XzMSPGJvTIW
github.com/hashicorp/terraform-plugin-sdk/v2 v2.6.1/go.mod h1:72j8cKfs9IirGhPMXJJWLTvRUK4zATtrCOvs2avDlo8=
github.com/hashicorp/vault/api v1.0.5-0.20200514164214-89b1987e38c2/go.mod h1:P8A7gn1a6j/7qQ4zOaWI6FC/Q9jQWEBRTOwZH33tC9o=
github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE=
github.com/hashicorp/vault/api v1.0.5-0.20200805123347-1ef507638af6 h1:ChHpobQse3kjVX7GmbpUFVqaMTf4lb1gcLrJltsUmS4=
github.com/hashicorp/vault/api v1.0.5-0.20200805123347-1ef507638af6/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk=
github.com/hashicorp/vault/api v1.1.0 h1:QcxC7FuqEl0sZaIjcXB/kNEeBa0DH5z57qbWBvZwLC4=
github.com/hashicorp/vault/api v1.1.0/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk=
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
github.com/hashicorp/vault/sdk v0.1.14-0.20200514144402-4bfac290c352/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
github.com/hashicorp/vault/sdk v0.1.14-0.20200514164214-89b1987e38c2/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10=
@@ -762,8 +756,6 @@ github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
@@ -900,7 +892,6 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/oracle/oci-go-sdk v12.5.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/oracle/oci-go-sdk v24.3.0+incompatible h1:x4mcfb4agelf1O4/1/auGlZ1lr97jXRSSN5MxTgG/zU=
github.com/oracle/oci-go-sdk v24.3.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888=
github.com/ory/dockertest/v3 v3.6.0 h1:I6KNJ6izxGduLACQii2SP/g7GN0JM9Xfaik6aAVaw6Y=
github.com/ory/dockertest/v3 v3.6.0/go.mod h1:4ZOpj8qBUmh8fcBSVzkH2bws2s91JdGvHUqan4GHEuQ=
github.com/ory/dockertest/v3 v3.6.5 h1:mhNKFeVEHuvaYW+/u+59mLzM/6XXGjpaet/yApgv+yc=
github.com/ory/dockertest/v3 v3.6.5/go.mod h1:iYKQSRlYrt/2s5fJWYdB98kCQG6g/LjBMvzEYii63vg=
@@ -932,8 +923,6 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac h1:jWKYCNlX4J5s8M0nHYkh7Y7c9gRVDEb3mq51j5J0F5M=
github.com/pquerna/cachecontrol v0.0.0-20201205024021-ac21108117ac/go.mod h1:hoLfEwdY11HjRfKFH6KqnPsfxlo3BP6bJehpDv8t6sQ=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
@@ -1023,6 +1012,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -1048,6 +1038,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tencentcloud/tencentcloud-sdk-go v1.0.162/go.mod h1:asUz5BPXxgoPGaRgZaVm1iGcUAuHyYUo1nXqKa83cvI=
github.com/tencentcloud/tencentcloud-sdk-go v3.0.171+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0=
@@ -1118,8 +1109,10 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.8.0 h1:CUhrE4N1rqSE6FM9ecihEjRkLQu8cDfgDyoOs83mEY4=
go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -1155,7 +1148,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
@@ -1190,8 +1182,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0 h1:8pl+sMODzuvGJkmj2W4kZihvVb5mKm8pB/X44PIQHv8=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -1245,7 +1237,6 @@ golang.org/x/net v0.0.0-20201029221708-28c70e62bb1d/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210326060303-6b1517762897 h1:KrsHThm5nFk34YtATK1LsThyGhGbGe1olrte/HInHvs=
golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
@@ -1331,27 +1322,24 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201029080932-201ba4db2418/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492 h1:Paq34FxTluEPvVyayQqMPgHm+vTOrIifmcYxFBx9TLg=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56 h1:b8jxX3zqjpqb2LklXPzKSGJhzyxCOZSz8ncv8Nv+y7w=
golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -1386,6 +1374,7 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -1426,9 +1415,8 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
golang.org/x/tools v0.0.0-20201002184944-ecd9fd270d5d/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -1541,10 +1529,8 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv
google.golang.org/grpc v1.35.0-dev.0.20201218190559-666aea1fb34c/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1 h1:ARnQJNWxGyYJpdf/JXscNlQr/uv607ZPU9Z7ogHi+iI=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+7 -7
View File
@@ -1,18 +1,18 @@
package provider
const (
// Key used for common SDK ID resource attribute
// IDKey is used for common SDK ID resource attribute
IDKey = "id"
// Key used for common "name" resource attribute
// NameKey is used for common "name" resource attribute
NameKey = "name"
// Key used for common "description" resource attribute
// DescriptionKey is used for common "description" resource attribute
DescriptionKey = "description"
// Key used for common "scope_id" resource attribute
// ScopeIdKey is used for common "scope_id" resource attribute
ScopeIdKey = "scope_id"
// Key used for common "type" resource attribute
// TypeKey is used for common "type" resource attribute
TypeKey = "type"
// Key used for common "host_catalog_id" resource attribute
// HostCatalogIdKey is used for common "host_catalog_id" resource attribute
HostCatalogIdKey = "host_catalog_id"
// Key used for common "auth_method_id" resource attribute
// AuthMethodIdKey is used for common "auth_method_id" resource attribute
AuthMethodIdKey = "auth_method_id"
)
+16 -14
View File
@@ -54,20 +54,22 @@ func New() *schema.Provider {
},
},
ResourcesMap: map[string]*schema.Resource{
"boundary_account": resourceAccount(),
"boundary_account_password": resourceAccountPassword(),
"boundary_account_oidc": resourceAccountOidc(),
"boundary_auth_method": resourceAuthMethod(),
"boundary_auth_method_password": resourceAuthMethodPassword(),
"boundary_auth_method_oidc": resourceAuthMethodOidc(),
"boundary_group": resourceGroup(),
"boundary_host": resourceHost(),
"boundary_host_catalog": resourceHostCatalog(),
"boundary_host_set": resourceHostset(),
"boundary_role": resourceRole(),
"boundary_scope": resourceScope(),
"boundary_target": resourceTarget(),
"boundary_user": resourceUser(),
"boundary_account": resourceAccount(),
"boundary_account_password": resourceAccountPassword(),
"boundary_account_oidc": resourceAccountOidc(),
"boundary_auth_method": resourceAuthMethod(),
"boundary_auth_method_password": resourceAuthMethodPassword(),
"boundary_auth_method_oidc": resourceAuthMethodOidc(),
"boundary_credential_library_vault": resourceCredentialLibraryVault(),
"boundary_credential_store_vault": resourceCredentialStoreVault(),
"boundary_group": resourceGroup(),
"boundary_host": resourceHost(),
"boundary_host_catalog": resourceHostCatalog(),
"boundary_host_set": resourceHostset(),
"boundary_role": resourceRole(),
"boundary_scope": resourceScope(),
"boundary_target": resourceTarget(),
"boundary_user": resourceUser(),
},
}
+1 -1
View File
@@ -19,7 +19,7 @@ var (
tcPassword = "passpass"
tcPAUM = "ampw_0000000000"
tcConfig = []controller.Option{
controller.WithDefaultAuthMethodId(tcPAUM),
controller.WithDefaultPasswordAuthMethodId(tcPAUM),
controller.WithDefaultLoginName(tcLoginName),
controller.WithDefaultPassword(tcPassword),
}
@@ -0,0 +1,237 @@
package provider
import (
"context"
"net/http"
"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"
)
const (
credentialStoreIdKey = "credential_store_id"
credentialLibraryVaultHttpMethodKey = "http_method"
credentialLibraryVaultHttpRequestBodyKey = "http_request_body"
credentialLibraryVaultPathKey = "path"
)
var libraryVaultAttrs = []string{
credentialLibraryVaultHttpMethodKey,
credentialLibraryVaultHttpRequestBodyKey,
credentialLibraryVaultPathKey,
}
func resourceCredentialLibraryVault() *schema.Resource {
return &schema.Resource{
Description: "The credential library for Vault resource allows you to configure a Boundary credential library for Vault.",
CreateContext: resourceCredentialLibraryCreateVault,
ReadContext: resourceCredentialLibraryReadVault,
UpdateContext: resourceCredentialLibraryUpdateVault,
DeleteContext: resourceCredentialLibraryDeleteVault,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
IDKey: {
Description: "The ID of the Vault credential library.",
Type: schema.TypeString,
Computed: true,
},
NameKey: {
Description: "The Vault credential library name. Defaults to the resource name.",
Type: schema.TypeString,
Optional: true,
},
DescriptionKey: {
Description: "The Vault credential library description.",
Type: schema.TypeString,
Optional: true,
},
credentialStoreIdKey: {
Description: "The ID of the credential store that this library belongs to.",
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
credentialLibraryVaultHttpMethodKey: {
Description: "The HTTP method to use when contacting Vault",
Type: schema.TypeString,
Optional: true,
},
credentialLibraryVaultHttpRequestBodyKey: {
Description: "The raw string to use in HTTP request to Vault",
Type: schema.TypeString,
Optional: true,
},
credentialLibraryVaultPathKey: {
Description: "The Vault path to query",
Type: schema.TypeString,
Required: true,
},
},
}
}
func setFromVaultCredentialLibraryResponseMap(d *schema.ResourceData, raw map[string]interface{}) 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{})
for _, v := range libraryVaultAttrs {
if err := d.Set(v, attrs[v]); err != nil {
return err
}
}
}
d.SetId(raw["id"].(string))
return nil
}
func resourceCredentialLibraryCreateVault(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
var opts []credentiallibraries.Option
if v, ok := d.GetOk(NameKey); ok {
opts = append(opts, credentiallibraries.WithName(v.(string)))
}
if v, ok := d.GetOk(DescriptionKey); ok {
opts = append(opts, credentiallibraries.WithDescription(v.(string)))
}
if v, ok := d.GetOk(credentialLibraryVaultHttpMethodKey); ok {
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryHttpMethod(v.(string)))
}
if v, ok := d.GetOk(credentialLibraryVaultHttpRequestBodyKey); ok {
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryHttpRequestBody(v.(string)))
}
if v, ok := d.GetOk(credentialLibraryVaultPathKey); ok {
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryPath(v.(string)))
}
var credentialStoreId string
cid, ok := d.GetOk(credentialStoreIdKey)
if ok {
credentialStoreId = cid.(string)
} else {
return diag.Errorf("no credential store ID is set")
}
client := credentiallibraries.NewClient(md.client)
cr, err := client.Create(ctx, credentialStoreId, opts...)
if err != nil {
return diag.Errorf("error creating credential library: %v", err)
}
if cr == nil {
return diag.Errorf("nil credential library after create")
}
if err := setFromVaultCredentialLibraryResponseMap(d, cr.GetResponse().Map); err != nil {
return diag.FromErr(err)
}
return nil
}
func resourceCredentialLibraryReadVault(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
client := credentiallibraries.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 library: %v", err)
}
if cr == nil {
return diag.Errorf("credential library nil after read")
}
if err := setFromVaultCredentialLibraryResponseMap(d, cr.GetResponse().Map); err != nil {
return diag.FromErr(err)
}
return nil
}
func resourceCredentialLibraryUpdateVault(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
client := credentiallibraries.NewClient(md.client)
var opts []credentiallibraries.Option
if d.HasChange(NameKey) {
opts = append(opts, credentiallibraries.DefaultName())
nameVal, ok := d.GetOk(NameKey)
if ok {
opts = append(opts, credentiallibraries.WithName(nameVal.(string)))
}
}
if d.HasChange(DescriptionKey) {
opts = append(opts, credentiallibraries.DefaultDescription())
descVal, ok := d.GetOk(DescriptionKey)
if ok {
opts = append(opts, credentiallibraries.WithDescription(descVal.(string)))
}
}
if d.HasChange(credentialLibraryVaultHttpMethodKey) {
opts = append(opts, credentiallibraries.DefaultVaultCredentialLibraryHttpMethod())
v, ok := d.GetOk(credentialLibraryVaultHttpMethodKey)
if ok {
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryHttpMethod(v.(string)))
}
}
if d.HasChange(credentialLibraryVaultHttpRequestBodyKey) {
opts = append(opts, credentiallibraries.DefaultVaultCredentialLibraryHttpRequestBody())
v, ok := d.GetOk(credentialLibraryVaultHttpRequestBodyKey)
if ok {
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryHttpRequestBody(v.(string)))
}
}
if d.HasChange(credentialLibraryVaultPathKey) {
v, ok := d.GetOk(credentialLibraryVaultPathKey)
if ok {
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryPath(v.(string)))
}
}
if len(opts) > 0 {
opts = append(opts, credentiallibraries.WithAutomaticVersioning(true))
aur, err := client.Update(ctx, d.Id(), 0, opts...)
if err != nil {
return diag.Errorf("error updating credential library: %v", err)
}
if err := setFromVaultCredentialLibraryResponseMap(d, aur.GetResponse().Map); err != nil {
return diag.Errorf("error setting credential library from response: %v", err)
}
}
return nil
}
func resourceCredentialLibraryDeleteVault(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
client := credentiallibraries.NewClient(md.client)
_, err := client.Delete(ctx, d.Id())
if err != nil {
return diag.Errorf("error deleting credential library: %v", err)
}
return nil
}
@@ -0,0 +1,154 @@
package provider
import (
"context"
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/credentiallibraries"
"github.com/hashicorp/boundary/testing/controller"
"github.com/hashicorp/boundary/testing/vault"
"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"
)
const (
vaultCredResc = "boundary_credential_library_vault.example"
vaultCredLibName = "foo"
vaultCredLibDesc = "the foo"
vaultCredLibPath = "/foo/bar"
vaultCredLibMethodGet = "GET"
vaultCredLibMethodPost = "POST"
vaultCredLibRequestBody = "foobar"
vaultCredLibStringUpdate = "_random"
)
var vaultCredLibResource = fmt.Sprintf(`
resource "boundary_credential_library_vault" "example" {
name = "%s"
description = "%s"
credential_store_id = boundary_credential_store_vault.example.id
path = "%s"
http_method = "%s"
}`, vaultCredLibName,
vaultCredLibDesc,
vaultCredLibPath,
vaultCredLibMethodGet)
var vaultCredLibResourceUpdate = fmt.Sprintf(`
resource "boundary_credential_library_vault" "example" {
name = "%s"
description = "%s"
credential_store_id = boundary_credential_store_vault.example.id
path = "%s"
http_method = "%s"
http_request_body = "%s"
}`, vaultCredLibName+vaultCredLibStringUpdate,
vaultCredLibDesc+vaultCredLibStringUpdate,
vaultCredLibPath+vaultCredLibStringUpdate,
vaultCredLibMethodPost,
vaultCredLibRequestBody)
func TestAccCredentialLibraryVault(t *testing.T) {
tc := controller.NewTestController(t, tcConfig...)
defer tc.Shutdown()
url := tc.ApiAddrs()[0]
vc := vault.NewTestVaultServer(t)
_, token := vc.CreateToken(t)
credStoreRes := vaultCredStoreResource(vc,
vaultCredStoreName,
vaultCredStoreDesc,
vaultCredStoreNamespace,
"www.original.com",
token,
true)
var provider *schema.Provider
resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories(&provider),
CheckDestroy: testAccCheckAuthMethodResourceDestroy(t, provider),
Steps: []resource.TestStep{
{
// create
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, vaultCredLibResource),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(vaultCredResc, NameKey, vaultCredLibName),
resource.TestCheckResourceAttr(vaultCredResc, DescriptionKey, vaultCredLibDesc),
resource.TestCheckResourceAttr(vaultCredResc, credentialLibraryVaultPathKey, vaultCredLibPath),
resource.TestCheckResourceAttr(vaultCredResc, credentialLibraryVaultHttpMethodKey, vaultCredLibMethodGet),
resource.TestCheckResourceAttr(vaultCredResc, credentialLibraryVaultHttpRequestBodyKey, ""),
testAccCheckCredentialLibraryVaultResourceExists(provider, vaultCredResc),
),
},
importStep(vaultCredResc),
{
// update
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, vaultCredLibResourceUpdate),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(vaultCredResc, NameKey, vaultCredLibName+vaultCredLibStringUpdate),
resource.TestCheckResourceAttr(vaultCredResc, DescriptionKey, vaultCredLibDesc+vaultCredLibStringUpdate),
resource.TestCheckResourceAttr(vaultCredResc, credentialLibraryVaultPathKey, vaultCredLibPath+vaultCredLibStringUpdate),
resource.TestCheckResourceAttr(vaultCredResc, credentialLibraryVaultHttpMethodKey, vaultCredLibMethodPost),
resource.TestCheckResourceAttr(vaultCredResc, credentialLibraryVaultHttpRequestBodyKey, vaultCredLibRequestBody),
testAccCheckCredentialLibraryVaultResourceExists(provider, vaultCredResc),
),
},
importStep(vaultCredResc),
},
})
}
func testAccCheckCredentialLibraryVaultResourceExists(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")
}
md := testProvider.Meta().(*metaData)
c := credentiallibraries.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 testAccCheckCredentialLibraryVaultResourceDestroy(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_library_vault":
id := rs.Primary.ID
c := credentiallibraries.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 vault credential library %q: %v", id, err)
}
default:
continue
}
}
return nil
}
}
@@ -0,0 +1,346 @@
package provider
import (
"context"
"net/http"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/credentialstores"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
const (
credentialStoreVaultAddressKey = "address"
credentialStoreVaultNamespaceKey = "namespace"
credentialStoreVaultCaCertKey = "ca_cert"
credentialStoreVaultTlsServerNameKey = "tls_server_name"
credentialStoreVaultTlsSkipVerifyKey = "tls_skip_verify"
credentialStoreVaultTokenKey = "token"
credentialStoreVaultTokenHmacKey = "token_hmac"
credentialStoreVaultClientCertificateKey = "client_certificate"
credentialStoreVaultClientCertificateKeyKey = "client_certificate_key"
credentialStoreVaultClientCertificateKeyHmacKey = "client_certificate_key_hmac"
credentialStoreType = "vault"
)
var storeVaultAttrs = []string{
credentialStoreVaultAddressKey,
credentialStoreVaultNamespaceKey,
credentialStoreVaultCaCertKey,
credentialStoreVaultTlsServerNameKey,
credentialStoreVaultTlsSkipVerifyKey,
credentialStoreVaultTokenHmacKey,
credentialStoreVaultClientCertificateKey,
credentialStoreVaultClientCertificateKeyHmacKey,
}
func resourceCredentialStoreVault() *schema.Resource {
return &schema.Resource{
Description: "The credential store for Vault resource allows you to configure a Boundary credential store for Vault.",
CreateContext: resourceCredentialStoreVaultCreate,
ReadContext: resourceCredentialStoreVaultRead,
UpdateContext: resourceCredentialStoreVaultUpdate,
DeleteContext: resourceCredentialStoreVaultDelete,
Importer: &schema.ResourceImporter{
StateContext: schema.ImportStatePassthroughContext,
},
Schema: map[string]*schema.Schema{
IDKey: {
Description: "The ID of the Vault credential store.",
Type: schema.TypeString,
Computed: true,
},
NameKey: {
Description: "The Vault credential store name. Defaults to the resource name.",
Type: schema.TypeString,
Optional: true,
},
DescriptionKey: {
Description: "The Vault credential store description.",
Type: schema.TypeString,
Optional: true,
},
ScopeIdKey: {
Description: "The scope for this credential store",
Type: schema.TypeString,
ForceNew: true,
Required: true,
},
credentialStoreVaultAddressKey: {
Description: "The address to Vault server",
Type: schema.TypeString,
Required: true,
},
credentialStoreVaultNamespaceKey: {
Description: "The namespace within Vault to use",
Type: schema.TypeString,
Optional: true,
},
credentialStoreVaultCaCertKey: {
Description: "The Vault CA certificate to use",
Type: schema.TypeString,
Optional: true,
},
credentialStoreVaultTlsServerNameKey: {
Description: "The Vault TLS server name",
Type: schema.TypeString,
Optional: true,
},
credentialStoreVaultTlsSkipVerifyKey: {
Description: "Whether or not to skip TLS verification",
Type: schema.TypeBool,
Optional: true,
},
credentialStoreVaultTokenKey: {
Description: "The Vault token",
Type: schema.TypeString,
Required: true,
Sensitive: true,
},
credentialStoreVaultTokenHmacKey: {
Description: "The Vault token hmac",
Type: schema.TypeString,
Computed: true,
},
credentialStoreVaultClientCertificateKey: {
Description: "The Vault client certificate",
Type: schema.TypeString,
Optional: true,
},
credentialStoreVaultClientCertificateKeyKey: {
Description: "The Vault client certificate key",
Type: schema.TypeString,
Optional: true,
Sensitive: true,
},
credentialStoreVaultClientCertificateKeyHmacKey: {
Description: "The Vault client certificate key hmac",
Type: schema.TypeString,
Computed: true,
},
},
}
}
func setFromVaultCredentialStoreResponseMap(d *schema.ResourceData, raw map[string]interface{}) 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(ScopeIdKey, raw[ScopeIdKey]); err != nil {
return err
}
if attrsVal, ok := raw["attributes"]; ok {
attrs := attrsVal.(map[string]interface{})
for _, v := range storeVaultAttrs {
if err := d.Set(v, attrs[v]); err != nil {
return err
}
}
}
d.SetId(raw["id"].(string))
return nil
}
func resourceCredentialStoreVaultCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
var opts []credentialstores.Option
if v, ok := d.GetOk(NameKey); ok {
opts = append(opts, credentialstores.WithName(v.(string)))
}
if v, ok := d.GetOk(DescriptionKey); ok {
opts = append(opts, credentialstores.WithDescription(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultAddressKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreAddress(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultNamespaceKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreNamespace(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultCaCertKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreCaCert(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultTlsServerNameKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreTlsServerName(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultTlsSkipVerifyKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreTlsSkipVerify(v.(bool)))
}
if v, ok := d.GetOk(credentialStoreVaultClientCertificateKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreClientCertificate(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultClientCertificateKeyKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreClientCertificateKey(v.(string)))
}
if v, ok := d.GetOk(credentialStoreVaultTokenKey); ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreToken(v.(string)))
}
var scope string
gotScope, ok := d.GetOk(ScopeIdKey)
if ok {
scope = gotScope.(string)
} else {
return diag.Errorf("no scope is set")
}
client := credentialstores.NewClient(md.client)
cr, err := client.Create(ctx, credentialStoreType, scope, opts...)
if err != nil {
return diag.Errorf("error creating credential store: %v", err)
}
if cr == nil {
return diag.Errorf("nil credential store after create")
}
if err := setFromVaultCredentialStoreResponseMap(d, cr.GetResponse().Map); err != nil {
return diag.Errorf("error generating credential store from response map: %v", err)
}
return nil
}
func resourceCredentialStoreVaultRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
client := credentialstores.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 store: %v", err)
}
if cr == nil {
return diag.Errorf("credential store nil after read")
}
if err := setFromVaultCredentialStoreResponseMap(d, cr.GetResponse().Map); err != nil {
return diag.Errorf("error generating credential store from response map: %v", err)
}
return nil
}
func resourceCredentialStoreVaultUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
client := credentialstores.NewClient(md.client)
var opts []credentialstores.Option
if d.HasChange(NameKey) {
opts = append(opts, credentialstores.DefaultName())
nameVal, ok := d.GetOk(NameKey)
if ok {
opts = append(opts, credentialstores.WithName(nameVal.(string)))
}
}
if d.HasChange(DescriptionKey) {
opts = append(opts, credentialstores.DefaultDescription())
descVal, ok := d.GetOk(DescriptionKey)
if ok {
opts = append(opts, credentialstores.WithDescription(descVal.(string)))
}
}
if d.HasChange(credentialStoreVaultAddressKey) {
v, ok := d.GetOk(credentialStoreVaultAddressKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreAddress(v.(string)))
}
}
if d.HasChange(credentialStoreVaultNamespaceKey) {
opts = append(opts, credentialstores.DefaultVaultCredentialStoreNamespace())
v, ok := d.GetOk(credentialStoreVaultNamespaceKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreNamespace(v.(string)))
}
}
if d.HasChange(credentialStoreVaultCaCertKey) {
opts = append(opts, credentialstores.DefaultVaultCredentialStoreCaCert())
v, ok := d.GetOk(credentialStoreVaultCaCertKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreCaCert(v.(string)))
}
}
if d.HasChange(credentialStoreVaultTlsServerNameKey) {
opts = append(opts, credentialstores.DefaultVaultCredentialStoreTlsServerName())
v, ok := d.GetOk(credentialStoreVaultTlsServerNameKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreTlsServerName(v.(string)))
}
}
if d.HasChange(credentialStoreVaultTlsSkipVerifyKey) {
opts = append(opts, credentialstores.DefaultVaultCredentialStoreTlsSkipVerify())
v, ok := d.GetOk(credentialStoreVaultTlsSkipVerifyKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreTlsSkipVerify(v.(bool)))
}
}
if d.HasChange(credentialStoreVaultTokenKey) {
v, ok := d.GetOk(credentialStoreVaultTokenKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreToken(v.(string)))
}
}
if d.HasChange(credentialStoreVaultClientCertificateKey) {
opts = append(opts, credentialstores.DefaultVaultCredentialStoreClientCertificate())
v, ok := d.GetOk(credentialStoreVaultClientCertificateKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreClientCertificate(v.(string)))
}
}
if d.HasChange(credentialStoreVaultClientCertificateKeyKey) {
opts = append(opts, credentialstores.DefaultVaultCredentialStoreClientCertificateKey())
v, ok := d.GetOk(credentialStoreVaultClientCertificateKeyKey)
if ok {
opts = append(opts, credentialstores.WithVaultCredentialStoreClientCertificateKey(v.(string)))
}
}
if len(opts) > 0 {
opts = append(opts, credentialstores.WithAutomaticVersioning(true))
crUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
if err != nil {
return diag.Errorf("error updating credential store: %v", err)
}
if crUpdate == nil {
return diag.Errorf("credential store nil after update")
}
if err = setFromVaultCredentialStoreResponseMap(d, crUpdate.GetResponse().Map); err != nil {
return diag.Errorf("error generating credential store from response map: %v", err)
}
}
return nil
}
func resourceCredentialStoreVaultDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
md := meta.(*metaData)
client := credentialstores.NewClient(md.client)
_, err := client.Delete(ctx, d.Id())
if err != nil {
return diag.Errorf("error deleting credential store: %v", err)
}
return nil
}
@@ -0,0 +1,191 @@
package provider
import (
"context"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/http"
"strings"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/credentialstores"
"github.com/hashicorp/boundary/testing/controller"
"github.com/hashicorp/boundary/testing/vault"
"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/blake2b"
)
const (
vaultCredStoreResc = "boundary_credential_store_vault.example"
vaultCredStoreName = "foo"
vaultCredStoreDesc = "the foo"
vaultCredStoreNamespace = "default"
vaultCredStoreUpdate = "_random"
)
func vaultCredStoreResource(vc *vault.TestVaultServer, name, description, namespace, tlsServer, token string, skipVerify bool) string {
caCert := fmt.Sprintf("\"%s\"", strings.Replace(string(vc.CaCert), "\n", `\n`, -1))
clientCert := fmt.Sprintf("\"%s\"", strings.Replace(string(vc.ClientCert), "\n", `\n`, -1))
clientKey := fmt.Sprintf("\"%s\"", strings.Replace(string(vc.ClientKey), "\n", `\n`, -1))
return fmt.Sprintf(`
resource "boundary_credential_store_vault" "example" {
name = "%s"
description = "%s"
scope_id = boundary_scope.proj1.id
address = "%s"
namespace = "%s"
ca_cert = %s
tls_server_name = "%s"
tls_skip_verify = "%v"
token = "%s"
client_certificate = %s
client_certificate_key = %s
depends_on = [boundary_role.proj1_admin]
}`, name,
description,
vc.Addr,
namespace,
caCert,
tlsServer,
skipVerify,
token,
clientCert,
clientKey)
}
func tokenHmac(token, accessor string) string {
key := blake2b.Sum256([]byte(accessor))
mac := hmac.New(sha256.New, key[:])
_, _ = mac.Write([]byte(token))
hmac := mac.Sum(nil)
return base64.RawURLEncoding.EncodeToString(hmac)
}
func TestAccCredentialStoreVault(t *testing.T) {
tc := controller.NewTestController(t, tcConfig...)
defer tc.Shutdown()
url := tc.ApiAddrs()[0]
vc := vault.NewTestVaultServer(t)
secret, token := vc.CreateToken(t)
tHmac := tokenHmac(token, secret.Auth.Accessor)
res := vaultCredStoreResource(vc,
vaultCredStoreName,
vaultCredStoreDesc,
vaultCredStoreNamespace,
"www.original.com",
token,
true)
vcUpdate := vault.NewTestVaultServer(t, vault.WithTestVaultTLS(vault.TestClientTLS))
secret, tokenUpdate := vcUpdate.CreateToken(t)
tHmacUpdate := tokenHmac(tokenUpdate, secret.Auth.Accessor)
resUpdate := vaultCredStoreResource(vcUpdate,
vaultCredStoreName+vaultCredStoreUpdate,
vaultCredStoreDesc+vaultCredStoreUpdate,
vaultCredStoreNamespace+vaultCredStoreUpdate,
"www.updated.com",
tokenUpdate,
false)
var provider *schema.Provider
resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories(&provider),
CheckDestroy: testAccCheckCredentialStoreVaultResourceDestroy(t, provider),
Steps: []resource.TestStep{
{
// create
Config: testConfig(url, fooOrg, firstProjectFoo, res),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(vaultCredStoreResc, NameKey, vaultCredStoreName),
resource.TestCheckResourceAttr(vaultCredStoreResc, DescriptionKey, vaultCredStoreDesc),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultAddressKey, vc.Addr),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultNamespaceKey, vaultCredStoreNamespace),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultCaCertKey, ""),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTlsServerNameKey, "www.original.com"),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTlsSkipVerifyKey, "true"),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTokenKey, token),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTokenHmacKey, tHmac),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultClientCertificateKey, ""),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultClientCertificateKeyKey, ""),
testAccCheckCredentialStoreVaultResourceExists(provider, vaultCredStoreResc),
),
},
importStep(vaultCredStoreResc, credentialStoreVaultTokenKey, credentialStoreVaultClientCertificateKeyKey),
{
// update
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(vaultCredStoreResc, NameKey, vaultCredStoreName+vaultCredStoreUpdate),
resource.TestCheckResourceAttr(vaultCredStoreResc, DescriptionKey, vaultCredStoreDesc+vaultCredStoreUpdate),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultAddressKey, vcUpdate.Addr),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultNamespaceKey, vaultCredStoreNamespace+vaultCredStoreUpdate),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultCaCertKey, string(vcUpdate.CaCert)),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTlsServerNameKey, "www.updated.com"),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTlsSkipVerifyKey, "false"),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTokenKey, tokenUpdate),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultTokenHmacKey, tHmacUpdate),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultClientCertificateKey, string(vcUpdate.ClientCert)),
resource.TestCheckResourceAttr(vaultCredStoreResc, credentialStoreVaultClientCertificateKeyKey, string(vcUpdate.ClientKey)),
testAccCheckCredentialStoreVaultResourceExists(provider, vaultCredStoreResc),
),
},
importStep(vaultCredStoreResc, credentialStoreVaultTokenKey, credentialStoreVaultClientCertificateKeyKey),
},
})
}
func testAccCheckCredentialStoreVaultResourceExists(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")
}
md := testProvider.Meta().(*metaData)
c := credentialstores.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 testAccCheckCredentialStoreVaultResourceDestroy(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_store_vault":
id := rs.Primary.ID
c := credentialstores.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 Vault credential store %q: %v", id, err)
}
default:
continue
}
}
return nil
}
}
-2
View File
@@ -196,13 +196,11 @@ func resourceGroupUpdate(ctx context.Context, d *schema.ResourceData, meta inter
if err := d.Set(NameKey, name); err != nil {
return diag.FromErr(err)
}
}
if d.HasChange(DescriptionKey) {
if err := d.Set(DescriptionKey, desc); err != nil {
return diag.FromErr(err)
}
}
// The above call may not actually happen, so we use d.Id() and automatic
+47 -1
View File
@@ -13,6 +13,7 @@ import (
const (
targetHostSetIdsKey = "host_set_ids"
targetCredentialLibraryIdsKey = "credential_library_ids"
targetDefaultPortKey = "default_port"
targetSessionMaxSecondsKey = "session_max_seconds"
targetSessionConnectionLimitKey = "session_connection_limit"
@@ -72,6 +73,12 @@ func resourceTarget() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
targetCredentialLibraryIdsKey: {
Description: "A list of credential library ID's.",
Type: schema.TypeSet,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
targetSessionMaxSecondsKey: {
Type: schema.TypeInt,
Optional: true,
@@ -107,6 +114,9 @@ func setFromTargetResponseMap(d *schema.ResourceData, raw map[string]interface{}
if err := d.Set(targetHostSetIdsKey, raw["host_set_ids"]); err != nil {
return err
}
if err := d.Set(targetCredentialLibraryIdsKey, raw["credential_library_ids"]); err != nil {
return err
}
if err := d.Set(targetSessionMaxSecondsKey, raw["session_max_seconds"]); err != nil {
return err
}
@@ -206,6 +216,15 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
}
}
var credentialLibraryIds []string
if credentialLibraryIdsVal, ok := d.GetOk(targetCredentialLibraryIdsKey); ok {
list := credentialLibraryIdsVal.(*schema.Set).List()
credentialLibraryIds = make([]string, 0, len(list))
for _, i := range list {
credentialLibraryIds = append(credentialLibraryIds, i.(string))
}
}
workerFilterVal, ok := d.GetOk(targetWorkerFilterKey)
if ok {
workerFilterStr := workerFilterVal.(string)
@@ -223,12 +242,22 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
}
raw := tcr.GetResponse().Map
version := tcr.Item.Version
if hostSetIds != nil {
tur, err := tc.SetHostSets(ctx, tcr.Item.Id, tcr.Item.Version, hostSetIds)
tur, err := tc.SetHostSets(ctx, tcr.Item.Id, version, hostSetIds)
if err != nil {
return diag.Errorf("error setting host sets on target: %v", err)
}
raw = tur.GetResponse().Map
version = tur.Item.Version
}
if credentialLibraryIds != nil {
tur, err := tc.SetCredentialLibraries(ctx, tcr.Item.Id, version, credentialLibraryIds)
if err != nil {
return diag.Errorf("error setting credential libraries on target: %v", err)
}
raw = tur.GetResponse().Map
}
if err := setFromTargetResponseMap(d, raw); err != nil {
@@ -400,6 +429,23 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
}
}
if d.HasChange(targetCredentialLibraryIdsKey) {
var credentialLibraryIds []string
if credentialLibraryIdsVal, ok := d.GetOk(targetCredentialLibraryIdsKey); ok {
credLibsIds := credentialLibraryIdsVal.(*schema.Set).List()
for _, credLibId := range credLibsIds {
credentialLibraryIds = append(credentialLibraryIds, credLibId.(string))
}
}
_, err := tc.SetCredentialLibraries(ctx, d.Id(), 0, credentialLibraryIds, targets.WithAutomaticVersioning(true))
if err != nil {
return diag.Errorf("error updating credential libraries in target: %v", err)
}
if err := d.Set(targetCredentialLibraryIdsKey, credentialLibraryIds); err != nil {
return diag.FromErr(err)
}
}
return nil
}
+122 -9
View File
@@ -6,6 +6,8 @@ import (
"net/http"
"testing"
"github.com/hashicorp/boundary/testing/vault"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/targets"
"github.com/hashicorp/boundary/testing/controller"
@@ -20,7 +22,7 @@ const (
)
var (
fooHostSet = `
fooBarHostSet = `
resource "boundary_host_catalog" "foo" {
type = "static"
name = "test"
@@ -49,10 +51,36 @@ resource "boundary_host_set" "foo" {
host_catalog_id = boundary_host_catalog.foo.id
host_ids = [
boundary_host.foo.id,
]
}
resource "boundary_host_set" "bar" {
name = "bar"
type = "static"
host_catalog_id = boundary_host_catalog.foo.id
host_ids = [
boundary_host.bar.id,
]
}`
fooBarCredLibs = `
resource "boundary_credential_library_vault" "foo" {
name = "foo"
description = "foo library"
credential_store_id = boundary_credential_store_vault.example.id
path = "foo/bar"
http_method = "GET"
}
resource "boundary_credential_library_vault" "bar" {
name = "bar"
description = "bar library"
credential_store_id = boundary_credential_store_vault.example.id
path = "bar/foo"
http_method = "GET"
}
`
fooTarget = fmt.Sprintf(`
resource "boundary_target" "foo" {
name = "test"
@@ -62,6 +90,9 @@ resource "boundary_target" "foo" {
host_set_ids = [
boundary_host_set.foo.id
]
credential_library_ids = [
boundary_credential_library_vault.foo.id
]
default_port = 22
depends_on = [boundary_role.proj1_admin]
session_max_seconds = 6000
@@ -76,7 +107,10 @@ resource "boundary_target" "foo" {
type = "tcp"
scope_id = boundary_scope.proj1.id
host_set_ids = [
boundary_host_set.foo.id
boundary_host_set.bar.id
]
credential_library_ids = [
boundary_credential_library_vault.bar.id
]
default_port = 80
depends_on = [boundary_role.proj1_admin]
@@ -92,6 +126,16 @@ func TestAccTarget(t *testing.T) {
defer tc.Shutdown()
url := tc.ApiAddrs()[0]
vc := vault.NewTestVaultServer(t)
_, token := vc.CreateToken(t)
credStoreRes := vaultCredStoreResource(vc,
vaultCredStoreName,
vaultCredStoreDesc,
vaultCredStoreNamespace,
"www.original.com",
token,
true)
var provider *schema.Provider
resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories(&provider),
@@ -99,7 +143,7 @@ func TestAccTarget(t *testing.T) {
Steps: []resource.TestStep{
{
// test create
Config: testConfig(url, fooOrg, firstProjectFoo, fooHostSet, fooTarget),
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, fooBarCredLibs, fooBarHostSet, fooTarget),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetResourceExists(provider, "boundary_target.foo"),
resource.TestCheckResourceAttr("boundary_target.foo", DescriptionKey, fooTargetDescription),
@@ -108,12 +152,14 @@ func TestAccTarget(t *testing.T) {
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionMaxSecondsKey, "6000"),
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "6"),
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "foo"`),
testAccCheckTargetResourceHostSet(provider, "boundary_target.foo", []string{"boundary_host_set.foo"}),
testAccCheckTargetResourceCredLibs(provider, "boundary_target.foo", []string{"boundary_credential_library_vault.foo"}),
),
},
importStep("boundary_target.foo"),
{
// test update
Config: testConfig(url, fooOrg, firstProjectFoo, fooHostSet, fooTargetUpdate),
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, fooBarCredLibs, fooBarHostSet, fooTargetUpdate),
Check: resource.ComposeTestCheckFunc(
testAccCheckTargetResourceExists(provider, "boundary_target.foo"),
resource.TestCheckResourceAttr("boundary_target.foo", DescriptionKey, fooTargetDescriptionUpdate),
@@ -121,6 +167,8 @@ func TestAccTarget(t *testing.T) {
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionMaxSecondsKey, "7000"),
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "7"),
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "bar"`),
testAccCheckTargetResourceHostSet(provider, "boundary_target.foo", []string{"boundary_host_set.bar"}),
testAccCheckTargetResourceCredLibs(provider, "boundary_target.foo", []string{"boundary_credential_library_vault.bar"}),
),
},
importStep("boundary_target.foo"),
@@ -128,7 +176,7 @@ func TestAccTarget(t *testing.T) {
})
}
func testAccCheckTargetResourceMembersSet(testProvider *schema.Provider, name string, hostSets []string) resource.TestCheckFunc {
func testAccCheckTargetResourceHostSet(testProvider *schema.Provider, name string, hostSets []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
@@ -141,7 +189,7 @@ func testAccCheckTargetResourceMembersSet(testProvider *schema.Provider, name st
}
// ensure host sets are declared in state
hostSetIDs := []string{}
var hostSetIDs []string
for _, hostSetResourceID := range hostSets {
hs, ok := s.RootModule().Resources[hostSetResourceID]
if !ok {
@@ -169,15 +217,80 @@ func testAccCheckTargetResourceMembersSet(testProvider *schema.Provider, name st
return fmt.Errorf("no hostSets found on target")
}
for _, stateHostSet := range t.Item.HostSetIds {
if len(t.Item.HostSetIds) != len(hostSetIDs) {
return fmt.Errorf("tf state and boundary have different number of host sets")
}
for _, stateHostSetId := range t.Item.HostSetIds {
ok := false
for _, gotHostSetID := range hostSetIDs {
if gotHostSetID == stateHostSet {
if gotHostSetID == stateHostSetId {
ok = true
}
}
if !ok {
return fmt.Errorf("host set in state not set in boundary: %s", stateHostSet)
return fmt.Errorf("host set id in state not set in boundary: %s", stateHostSetId)
}
}
return nil
}
}
func testAccCheckTargetResourceCredLibs(testProvider *schema.Provider, name string, credLibs []string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("target resource not found: %s", name)
}
id := rs.Primary.ID
if id == "" {
return fmt.Errorf("target resource ID is not set")
}
// ensure host sets are declared in state
var credLibIDs []string
for _, credLibResourceID := range credLibs {
cl, ok := s.RootModule().Resources[credLibResourceID]
if !ok {
return fmt.Errorf("credential library resource not found: %s", credLibResourceID)
}
credLibID := cl.Primary.ID
if id == "" {
return fmt.Errorf("credential library resource ID not set")
}
credLibIDs = append(credLibIDs, credLibID)
}
// check boundary to ensure it matches
md := testProvider.Meta().(*metaData)
tgtsClient := targets.NewClient(md.client)
t, err := tgtsClient.Read(context.Background(), id)
if err != nil {
return fmt.Errorf("Got an error when reading target %q: %v", id, err)
}
if len(t.Item.CredentialLibraries) == 0 {
return fmt.Errorf("no credential libraries found on target")
}
if len(t.Item.CredentialLibraries) != len(credLibIDs) {
return fmt.Errorf("tf state and boundary have different number of credential libraries")
}
for _, stateCredLibId := range t.Item.CredentialLibraryIds {
ok := false
for _, gotCredLibID := range credLibIDs {
if gotCredLibID == stateCredLibId {
ok = true
}
}
if !ok {
return fmt.Errorf("credential library id in state not set in boundary: %s", stateCredLibId)
}
}