Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24bd9521f4 | ||
|
|
ef38f78c46 | ||
|
|
6255122fba | ||
|
|
622fca1c0e | ||
|
|
8aa93ccb69 | ||
|
|
1b96f89728 | ||
|
|
e90db9895c | ||
|
|
7ae01cc6e0 | ||
|
|
a134747539 | ||
|
|
893b150ec9 | ||
|
|
a61a13193c | ||
|
|
292204caf0 | ||
|
|
a2e04949be | ||
|
|
8fad44cc94 | ||
|
|
e0fb0a44e0 | ||
|
|
767a9ce1e6 | ||
|
|
f1d8cbf6e6 | ||
|
|
072c046b67 | ||
|
|
82ae1e3cd7 | ||
|
|
14bc6a4453 | ||
|
|
dc3aa09688 | ||
|
|
d6fb6d4c16 | ||
|
|
7164883b1b | ||
|
|
7f600f1cd5 | ||
|
|
145c91305c | ||
|
|
deb02086e3 | ||
|
|
445398286f | ||
|
|
66aad543f6 | ||
|
|
b491b4d123 | ||
|
|
bf34f12c56 | ||
|
|
0f4126d7d0 | ||
|
|
41a58f4db5 | ||
|
|
56f858006e | ||
|
|
48672fd050 | ||
|
|
5859c55f43 | ||
|
|
fe704abbfc | ||
|
|
e734090217 | ||
|
|
f9b5452b84 | ||
|
|
531dfa486a | ||
|
|
0bbc96fc11 |
No files matched your search
+1
-1
@@ -1 +1 @@
|
|||||||
1.18.1
|
1.19.1
|
||||||
@@ -1,3 +1,65 @@
|
|||||||
|
# Boundary Terraform Provider CHANGELOG
|
||||||
|
|
||||||
|
Canonical reference for changes, improvements, and bugfixes for the Boundary Terraform provider.
|
||||||
|
|
||||||
|
## 1.1.1 (October 12, 2022)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* The plugin cleanup function is being called before the entire Terraform workflow is complete.
|
||||||
|
([Issue](https://github.com/hashicorp/terraform-provider-boundary/issues/282)),
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/285)).
|
||||||
|
|
||||||
|
## 1.1.0 (October 4, 2022)
|
||||||
|
|
||||||
|
### New and Improved
|
||||||
|
|
||||||
|
* Add support for JSON credentials
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/271)).
|
||||||
|
* Add support for setting the plugin execution directory from the config
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/280)).
|
||||||
|
|
||||||
|
### Deprecations/Changes
|
||||||
|
|
||||||
|
* Fix panic resulting from expired Vault credential store tokens
|
||||||
|
([Issue](https://github.com/hashicorp/terraform-provider-boundary/issues/279),
|
||||||
|
[PR](https://github.com/hashicorp/terraform-provider-boundary/pull/277)).
|
||||||
|
* Remove `application_credential_source_ids` of the `target` resource which was deprecated
|
||||||
|
in 1.0.12 ([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/273)).
|
||||||
|
* Remove `default_role` from the `role` resource, this schema was never supported and was
|
||||||
|
included mistakenly ([Issue](https://github.com/hashicorp/terraform-provider-boundary/issues/130),
|
||||||
|
[PR](https://github.com/hashicorp/terraform-provider-boundary/pull/269)).
|
||||||
|
|
||||||
|
## 1.0.12 (September 13, 2022)
|
||||||
|
|
||||||
|
### New and Improved
|
||||||
|
|
||||||
|
* Add support for SSH targets
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/264)).
|
||||||
|
|
||||||
|
### Deprecations/Changes
|
||||||
|
|
||||||
|
* Deprecate `application_credential_source_ids` of the `target` resource
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/260)).
|
||||||
|
|
||||||
|
## 1.0.11 (August 26, 2022)
|
||||||
|
|
||||||
|
### New and Improved
|
||||||
|
|
||||||
|
* Add support for SSH private key credentials
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/257)).
|
||||||
|
* Add support for credential type in Vault libraries
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/257)).
|
||||||
|
|
||||||
|
## 1.0.10 (August 10, 2022)
|
||||||
|
|
||||||
|
### New and Improved
|
||||||
|
|
||||||
|
* Adds support for static credential stores
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/236)).
|
||||||
|
* Adds support for username password credentials
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/242)).
|
||||||
|
|
||||||
## 1.0.9 (June 6, 2022)
|
## 1.0.9 (June 6, 2022)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
FROM golang:1.18
|
FROM golang:1.19
|
||||||
|
|
||||||
WORKDIR /go/src/terraform-provider-boundary
|
WORKDIR /go/src/terraform-provider-boundary
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
Copyright (c) 2020 HashiCorp, Inc.
|
||||||
|
|
||||||
Mozilla Public License Version 2.0
|
Mozilla Public License Version 2.0
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ Requirements
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
- [Terraform](https://www.terraform.io/downloads.html) >= 0.12.x
|
- [Terraform](https://www.terraform.io/downloads.html) >= 0.12.x
|
||||||
- [Go](https://golang.org/doc/install) >= 1.18
|
- [Go](https://golang.org/doc/install) >= 1.19
|
||||||
|
|
||||||
Building The Provider
|
Building The Provider
|
||||||
---------------------
|
---------------------
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
VERSION="1.18.1"
|
VERSION="1.19.1"
|
||||||
|
|
||||||
[ -z "$GOROOT" ] && GOROOT="$HOME/.go"
|
[ -z "$GOROOT" ] && GOROOT="$HOME/.go"
|
||||||
[ -z "$GOPATH" ] && GOPATH="$HOME/go"
|
[ -z "$GOPATH" ] && GOPATH="$HOME/go"
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ provider "boundary" {
|
|||||||
- `auth_method_id` (String) The auth method ID e.g. ampw_1234567890
|
- `auth_method_id` (String) The auth method ID e.g. ampw_1234567890
|
||||||
- `password_auth_method_login_name` (String) The auth method login name for password-style auth methods
|
- `password_auth_method_login_name` (String) The auth method login name for password-style auth methods
|
||||||
- `password_auth_method_password` (String) The auth method password for password-style auth methods
|
- `password_auth_method_password` (String) The auth method password for password-style auth methods
|
||||||
|
- `plugin_execution_dir` (String) Specifies a directory that the Boundary provider can use to write and execute its built-in plugins.
|
||||||
- `recovery_kms_hcl` (String) Can be a heredoc string or a path on disk. If set, the string/file will be parsed as HCL and used with the recovery KMS mechanism. While this is set, it will override any other authentication information; the KMS mechanism will always be used. See Boundary's KMS docs for examples: https://boundaryproject.io/docs/configuration/kms
|
- `recovery_kms_hcl` (String) Can be a heredoc string or a path on disk. If set, the string/file will be parsed as HCL and used with the recovery KMS mechanism. While this is set, it will override any other authentication information; the KMS mechanism will always be used. See Boundary's KMS docs for examples: https://boundaryproject.io/docs/configuration/kms
|
||||||
- `tls_insecure` (Boolean) When set to true, does not validate the Boundary API endpoint certificate
|
- `tls_insecure` (Boolean) When set to true, does not validate the Boundary API endpoint certificate
|
||||||
- `token` (String) The Boundary token to use, as a string or path on disk containing just the string. If set, the token read here will be used in place of authenticating with the auth method specified in "auth_method_id", although the recovery KMS mechanism will still override this. Can also be set with the BOUNDARY_TOKEN environment variable.
|
- `token` (String) The Boundary token to use, as a string or path on disk containing just the string. If set, the token read here will be used in place of authenticating with the auth method specified in "auth_method_id", although the recovery KMS mechanism will still override this. Can also be set with the BOUNDARY_TOKEN environment variable.
|
||||||
@@ -3,12 +3,12 @@
|
|||||||
page_title: "boundary_account Resource - terraform-provider-boundary"
|
page_title: "boundary_account Resource - terraform-provider-boundary"
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
description: |-
|
description: |-
|
||||||
Deprecated: use resource_account_password instead.
|
Deprecated: use boundary_account_password instead.
|
||||||
---
|
---
|
||||||
|
|
||||||
# boundary_account (Resource)
|
# boundary_account (Resource)
|
||||||
|
|
||||||
Deprecated: use `resource_account_password` instead.
|
Deprecated: use `boundary_account_password` instead.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ Deprecated: use `resource_account_password` instead.
|
|||||||
- `description` (String) The account description.
|
- `description` (String) The account description.
|
||||||
- `login_name` (String) The login name for this account.
|
- `login_name` (String) The login name for this account.
|
||||||
- `name` (String) The account name. Defaults to the resource name.
|
- `name` (String) The account name. Defaults to the resource name.
|
||||||
- `password` (String) The account password. Only set on create, changes will not be reflected when updating account.
|
- `password` (String, Sensitive) The account password. Only set on create, changes will not be reflected when updating account.
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ resource "boundary_account_password" "jeff" {
|
|||||||
- `description` (String) The account description.
|
- `description` (String) The account description.
|
||||||
- `login_name` (String) The login name for this account.
|
- `login_name` (String) The login name for this account.
|
||||||
- `name` (String) The account name. Defaults to the resource name.
|
- `name` (String) The account name. Defaults to the resource name.
|
||||||
- `password` (String) The account password. Only set on create, changes will not be reflected when updating account.
|
- `password` (String, Sensitive) The account password. Only set on create, changes will not be reflected when updating account.
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ The OIDC auth method resource allows you to configure a Boundary auth_method_oid
|
|||||||
- `callback_url` (String) The URL that should be provided to the IdP for callbacks.
|
- `callback_url` (String) The URL that should be provided to the IdP for callbacks.
|
||||||
- `claims_scopes` (List of String) Claims scopes.
|
- `claims_scopes` (List of String) Claims scopes.
|
||||||
- `client_id` (String) The client ID assigned to this auth method from the provider.
|
- `client_id` (String) The client ID assigned to this auth method from the provider.
|
||||||
- `client_secret` (String) The secret key assigned to this auth method from the provider. Once set, only the hash will be kept and the original value can be removed from configuration.
|
- `client_secret` (String, Sensitive) The secret key assigned to this auth method from the provider. Once set, only the hash will be kept and the original value can be removed from configuration.
|
||||||
- `client_secret_hmac` (String) The HMAC of the client secret returned by the Boundary controller, which is used for comparison after initial setting of the value.
|
- `client_secret_hmac` (String) The HMAC of the client secret returned by the Boundary controller, which is used for comparison after initial setting of the value.
|
||||||
- `description` (String) The auth method description.
|
- `description` (String) The auth method description.
|
||||||
- `disable_discovered_config_validation` (Boolean) Disables validation logic ensuring that the OIDC provider's information from its discovery endpoint matches the information here. The validation is only performed at create or update time.
|
- `disable_discovered_config_validation` (Boolean) Disables validation logic ensuring that the OIDC provider's information from its discovery endpoint matches the information here. The validation is only performed at create or update time.
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "boundary_credential_json Resource - terraform-provider-boundary"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
The json credential resource allows you to congiure a credential using a json object.
|
||||||
|
---
|
||||||
|
|
||||||
|
# boundary_credential_json (Resource)
|
||||||
|
|
||||||
|
The json credential resource allows you to congiure a credential using a json object.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_json" "example" {
|
||||||
|
name = "example_json"
|
||||||
|
description = "My first json credential!"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
object = file("~/object.json") # change to valid json file
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- `credential_store_id` (String) The credential store in which to save this json credential.
|
||||||
|
- `object` (String, Sensitive) The object for the this json credential. Either values encoded with the "jsonencode" function, pre-escaped JSON string, or a file
|
||||||
|
|
||||||
|
### Optional
|
||||||
|
|
||||||
|
- `description` (String) The description of this json credential.
|
||||||
|
- `name` (String) The name of this json credential. Defaults to the resource name.
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- `id` (String) The ID of this json credential.
|
||||||
|
- `object_hmac` (String) The object hmac.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_credential_json.example_json <my-id>
|
||||||
|
```
|
||||||
@@ -68,6 +68,7 @@ EOT
|
|||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
|
- `credential_type` (String) The type of credential the library generates.
|
||||||
- `description` (String) The Vault credential library description.
|
- `description` (String) The Vault credential library description.
|
||||||
- `http_method` (String) The HTTP method the library uses when requesting credentials from Vault. Defaults to 'GET'
|
- `http_method` (String) The HTTP method the library uses when requesting credentials from Vault. Defaults to 'GET'
|
||||||
- `http_request_body` (String) The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.
|
- `http_request_body` (String) The body of the HTTP request the library sends to Vault when requesting credentials. Only valid if `http_method` is set to `POST`.
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "boundary_credential_ssh_private_key Resource - terraform-provider-boundary"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
The SSH private key credential resource allows you to configure a credential using a username, private key and optional passphrase.
|
||||||
|
---
|
||||||
|
|
||||||
|
# boundary_credential_ssh_private_key (Resource)
|
||||||
|
|
||||||
|
The SSH private key credential resource allows you to configure a credential using a username, private key and optional passphrase.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_ssh_private_key" "example" {
|
||||||
|
name = "example_ssh_private_key"
|
||||||
|
description = "My first ssh private key credential!"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
username = "my-username"
|
||||||
|
private_key = file("~/.ssh/id_rsa") # change to valid SSH Private Key
|
||||||
|
private_key_passphrase = "optional-passphrase" # change to the passphrase of the Private Key if required
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- `credential_store_id` (String) ID of the credential store this credential belongs to.
|
||||||
|
- `private_key` (String, Sensitive) The private key associated with the credential.
|
||||||
|
- `username` (String) The username associated with the credential.
|
||||||
|
|
||||||
|
### Optional
|
||||||
|
|
||||||
|
- `description` (String) The description of the credential.
|
||||||
|
- `name` (String) The name of the credential. Defaults to the resource name.
|
||||||
|
- `private_key_passphrase` (String, Sensitive) The passphrase of the private key associated with the credential.
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- `id` (String) The ID of the credential.
|
||||||
|
- `private_key_hmac` (String) The private key hmac.
|
||||||
|
- `private_key_passphrase_hmac` (String) The private key passphrase hmac.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_credential_ssh_private_key.example_ssh_private_key <my-id>
|
||||||
|
```
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "boundary_credential_store_static Resource - terraform-provider-boundary"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
The static credential store resource allows you to configure a Boundary static credential store.
|
||||||
|
---
|
||||||
|
|
||||||
|
# boundary_credential_store_static (Resource)
|
||||||
|
|
||||||
|
The static credential store resource allows you to configure a Boundary static credential store.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- `scope_id` (String) The scope for this credential store.
|
||||||
|
|
||||||
|
### Optional
|
||||||
|
|
||||||
|
- `description` (String) The static credential store description.
|
||||||
|
- `name` (String) The static credential store name. Defaults to the resource name.
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- `id` (String) The ID of the static credential store.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_credential_store_static.example_static_credential_store <my-id>
|
||||||
|
```
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
---
|
||||||
|
# generated by https://github.com/hashicorp/terraform-plugin-docs
|
||||||
|
page_title: "boundary_credential_username_password Resource - terraform-provider-boundary"
|
||||||
|
subcategory: ""
|
||||||
|
description: |-
|
||||||
|
The username/password credential resource allows you to configure a credential using a username and password pair.
|
||||||
|
---
|
||||||
|
|
||||||
|
# boundary_credential_username_password (Resource)
|
||||||
|
|
||||||
|
The username/password credential resource allows you to configure a credential using a username and password pair.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_username_password" "example" {
|
||||||
|
name = "example_username_password"
|
||||||
|
description = "My first username password credential!"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
username = "my-username"
|
||||||
|
password = "my-password"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- schema generated by tfplugindocs -->
|
||||||
|
## Schema
|
||||||
|
|
||||||
|
### Required
|
||||||
|
|
||||||
|
- `credential_store_id` (String) The credential store in which to save this username/password credential.
|
||||||
|
- `password` (String, Sensitive) The password of this username/password credential.
|
||||||
|
- `username` (String) The username of this username/password credential.
|
||||||
|
|
||||||
|
### Optional
|
||||||
|
|
||||||
|
- `description` (String) The description of this username/password credential.
|
||||||
|
- `name` (String) The name of this username/password credential. Defaults to the resource name.
|
||||||
|
|
||||||
|
### Read-Only
|
||||||
|
|
||||||
|
- `id` (String) The ID of this username/password credential.
|
||||||
|
- `password_hmac` (String) The password hmac.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_credential_username_password.example_username_password <my-id>
|
||||||
|
```
|
||||||
@@ -3,12 +3,12 @@
|
|||||||
page_title: "boundary_host Resource - terraform-provider-boundary"
|
page_title: "boundary_host Resource - terraform-provider-boundary"
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
description: |-
|
description: |-
|
||||||
Deprecated: use resource_host_static instead.
|
Deprecated: use boundary_host_static instead.
|
||||||
---
|
---
|
||||||
|
|
||||||
# boundary_host (Resource)
|
# boundary_host (Resource)
|
||||||
|
|
||||||
Deprecated: use `resource_host_static` instead.
|
Deprecated: use `boundary_host_static` instead.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
page_title: "boundary_host_catalog Resource - terraform-provider-boundary"
|
page_title: "boundary_host_catalog Resource - terraform-provider-boundary"
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
description: |-
|
description: |-
|
||||||
Deprecated: use resource_host_catalog_static instead.
|
Deprecated: use boundary_host_catalog_static instead.
|
||||||
---
|
---
|
||||||
|
|
||||||
# boundary_host_catalog (Resource)
|
# boundary_host_catalog (Resource)
|
||||||
|
|
||||||
Deprecated: use `resource_host_catalog_static` instead.
|
Deprecated: use `boundary_host_catalog_static` instead.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,70 @@ description: |-
|
|||||||
|
|
||||||
The host catalog resource allows you to configure a Boundary plugin-type host catalog. Host catalogs are always part of a project, so a project resource should be used inline or you should have the project ID in hand to successfully configure a host catalog.
|
The host catalog resource allows you to configure a Boundary plugin-type host catalog. Host catalogs are always part of a project, so a project resource should be used inline or you should have the project ID in hand to successfully configure a host catalog.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.global.id
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the aws plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-aws
|
||||||
|
#
|
||||||
|
# For more information about aws users, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/aws-host-catalogs?in=boundary/oss-access-management#configure-terraform-and-iam-user-privileges
|
||||||
|
resource "boundary_host_catalog_plugin" "aws_example" {
|
||||||
|
name = "My aws catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "aws"
|
||||||
|
attributes_json = jsonencode({ "region" = "us-east-1" })
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in aws by creating a aws iam user with programmatic access
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"access_key_id" = "aws_access_key_id_value",
|
||||||
|
"secret_access_key" = "aws_secret_access_key_value"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the azure plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-azure
|
||||||
|
#
|
||||||
|
# For more information about azure ad applications, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/azure-host-catalogs#register-a-new-azure-ad-application-1
|
||||||
|
resource "boundary_host_catalog_plugin" "azure_example" {
|
||||||
|
name = "My azure catalog"
|
||||||
|
description = "My second host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "azure"
|
||||||
|
|
||||||
|
# the attributes below must be generated in azure by creating an ad application
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"disable_credential_rotation" = "true",
|
||||||
|
"tenant_id" = "ARM_TENANT_ID",
|
||||||
|
"subscription_id" = "ARM_SUBSCRIPTION_ID",
|
||||||
|
"client_id" = "ARM_CLIENT_ID"
|
||||||
|
})
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in azure by creating an ad application
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"secret_value" = "ARM_CLIENT_SECRET"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
<!-- schema generated by tfplugindocs -->
|
<!-- schema generated by tfplugindocs -->
|
||||||
## Schema
|
## Schema
|
||||||
@@ -36,4 +99,10 @@ The host catalog resource allows you to configure a Boundary plugin-type host ca
|
|||||||
|
|
||||||
- `id` (String) The ID of the host catalog.
|
- `id` (String) The ID of the host catalog.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_host_catalog_plugin.foo <my-id>
|
||||||
|
```
|
||||||
@@ -10,7 +10,30 @@ description: |-
|
|||||||
|
|
||||||
The static host catalog resource allows you to configure a Boundary static-type host catalog. Host catalogs are always part of a project, so a project resource should be used inline or you should have the project ID in hand to successfully configure a host catalog.
|
The static host catalog resource allows you to configure a Boundary static-type host catalog. Host catalogs are always part of a project, so a project resource should be used inline or you should have the project ID in hand to successfully configure a host catalog.
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.global.id
|
||||||
|
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_host_catalog_static" "example" {
|
||||||
|
name = "My catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
<!-- schema generated by tfplugindocs -->
|
<!-- schema generated by tfplugindocs -->
|
||||||
## Schema
|
## Schema
|
||||||
@@ -28,4 +51,10 @@ The static host catalog resource allows you to configure a Boundary static-type
|
|||||||
|
|
||||||
- `id` (String) The ID of the host catalog.
|
- `id` (String) The ID of the host catalog.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_host_catalog_static.foo <my-id>
|
||||||
|
```
|
||||||
@@ -3,12 +3,12 @@
|
|||||||
page_title: "boundary_host_set Resource - terraform-provider-boundary"
|
page_title: "boundary_host_set Resource - terraform-provider-boundary"
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
description: |-
|
description: |-
|
||||||
Deprecated: use resource_host_set_static instead.
|
Deprecated: use boundary_host_set_static instead.
|
||||||
---
|
---
|
||||||
|
|
||||||
# boundary_host_set (Resource)
|
# boundary_host_set (Resource)
|
||||||
|
|
||||||
Deprecated: use `resource_host_set_static` instead.
|
Deprecated: use `boundary_host_set_static` instead.
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,113 @@ description: |-
|
|||||||
|
|
||||||
The host_set_plugin resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
The host_set_plugin resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the aws plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-aws
|
||||||
|
#
|
||||||
|
# For more information about aws users, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/aws-host-catalogs?in=boundary/oss-access-management#configure-terraform-and-iam-user-privileges
|
||||||
|
resource "boundary_host_catalog_plugin" "aws_example" {
|
||||||
|
name = "My aws catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "aws"
|
||||||
|
attributes_json = jsonencode({ "region" = "us-east-1" })
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in aws by creating a aws iam user with programmatic access
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"access_key_id" = "aws_access_key_id_value",
|
||||||
|
"secret_access_key" = "aws_secret_access_key_value"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "web" {
|
||||||
|
name = "My web host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.aws_exmaple.id
|
||||||
|
attributes_json = jsonencode({ "filters" = "tag:service-type=web" })
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "foobar" {
|
||||||
|
name = "My foobar host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.aws_exmaple.id
|
||||||
|
preferred_endpoints = ["cidr:54.0.0.0/8"]
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"filters" = "tag-key=foo",
|
||||||
|
"filters" = "tag-key=bar"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "launch" {
|
||||||
|
name = "My launch host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.aws_exmaple.id
|
||||||
|
sync_interval_seconds = 60
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"filters" = "tag:development=prod,dev",
|
||||||
|
"filters" = "launch-time=2022-01-04T*"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the azure plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-azure
|
||||||
|
#
|
||||||
|
# For more information about azure ad applications, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/azure-host-catalogs#register-a-new-azure-ad-application-1
|
||||||
|
resource "boundary_host_catalog_plugin" "azure_example" {
|
||||||
|
name = "My azure catalog"
|
||||||
|
description = "My second host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "azure"
|
||||||
|
|
||||||
|
# the attributes below must be generated in azure by creating an ad application
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"disable_credential_rotation" = "true",
|
||||||
|
"tenant_id" = "ARM_TENANT_ID",
|
||||||
|
"subscription_id" = "ARM_SUBSCRIPTION_ID",
|
||||||
|
"client_id" = "ARM_CLIENT_ID"
|
||||||
|
})
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in azure by creating an ad application
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"secret_value" = "ARM_CLIENT_SECRET"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "database" {
|
||||||
|
name = "My database host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.azure_exmaple.id
|
||||||
|
attributes_json = jsonencode({ "filter" = "tagName eq 'service-type' and tagValue eq 'database'" })
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "foodev" {
|
||||||
|
name = "My foodev host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.azure_exmaple.id
|
||||||
|
preferred_endpoints = ["cidr:54.0.0.0/8"]
|
||||||
|
sync_interval_seconds = 60
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"filter" = "tagName eq 'tag-key' and tagValue eq 'foo'",
|
||||||
|
"filter" = "tagName eq 'application' and tagValue eq 'dev'",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
<!-- schema generated by tfplugindocs -->
|
<!-- schema generated by tfplugindocs -->
|
||||||
## Schema
|
## Schema
|
||||||
@@ -32,4 +138,10 @@ The host_set_plugin resource allows you to configure a Boundary host set. Host s
|
|||||||
|
|
||||||
- `id` (String) The ID of the host set.
|
- `id` (String) The ID of the host set.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_host_set_plugin.foo <my-id>
|
||||||
|
```
|
||||||
@@ -10,7 +10,50 @@ description: |-
|
|||||||
|
|
||||||
The host_set_static resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
The host_set_static resource allows you to configure a Boundary host set. Host sets are always part of a host catalog, so a host catalog resource should be used inline or you should have the host catalog ID in hand to successfully configure a host set.
|
||||||
|
|
||||||
|
## 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_host_catalog_static" "example" {
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_static" "first" {
|
||||||
|
name = "host_1"
|
||||||
|
description = "My first host!"
|
||||||
|
address = "10.0.0.1"
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_static" "second" {
|
||||||
|
name = "host_2"
|
||||||
|
description = "My second host!"
|
||||||
|
address = "10.0.0.2"
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_static" "web" {
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
host_ids = [
|
||||||
|
boundary_host_static.first.id,
|
||||||
|
boundary_host_static.second.id,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
<!-- schema generated by tfplugindocs -->
|
<!-- schema generated by tfplugindocs -->
|
||||||
## Schema
|
## Schema
|
||||||
@@ -30,4 +73,10 @@ The host_set_static resource allows you to configure a Boundary host set. Host s
|
|||||||
|
|
||||||
- `id` (String) The ID of the host set.
|
- `id` (String) The ID of the host set.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_host_set_static.foo <my-id>
|
||||||
|
```
|
||||||
@@ -10,7 +10,37 @@ description: |-
|
|||||||
|
|
||||||
The static host resource allows you to configure a Boundary static host. Hosts are always part of a project, so a project resource should be used inline or you should have the project ID in hand to successfully configure a host.
|
The static host resource allows you to configure a Boundary static host. Hosts are always part of a project, so a project resource should be used inline or you should have the project ID in hand to successfully configure a host.
|
||||||
|
|
||||||
|
## 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_host_catalog_static" "example" {
|
||||||
|
name = "My catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_static" "example" {
|
||||||
|
name = "example_host"
|
||||||
|
description = "My first host!"
|
||||||
|
address = "10.0.0.1"
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
<!-- schema generated by tfplugindocs -->
|
<!-- schema generated by tfplugindocs -->
|
||||||
## Schema
|
## Schema
|
||||||
@@ -30,4 +60,10 @@ The static host resource allows you to configure a Boundary static host. Hosts a
|
|||||||
|
|
||||||
- `id` (String) The ID of the host.
|
- `id` (String) The ID of the host.
|
||||||
|
|
||||||
|
## Import
|
||||||
|
|
||||||
|
Import is supported using the following syntax:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
terraform import boundary_host_static.foo <my-id>
|
||||||
|
```
|
||||||
@@ -126,7 +126,6 @@ resource "boundary_role" "readonly" {
|
|||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
- `default_role` (Boolean) Indicates that the role containing this value is the default role (that is, has the id 'r_default'), which triggers some specialized behavior to allow it to be imported and managed.
|
|
||||||
- `description` (String) The role description.
|
- `description` (String) The role description.
|
||||||
- `grant_scope_id` (String)
|
- `grant_scope_id` (String)
|
||||||
- `grant_strings` (Set of String) A list of stringified grants for the role.
|
- `grant_strings` (Set of String) A list of stringified grants for the role.
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ resource "boundary_credential_library_vault" "foo" {
|
|||||||
credential_store_id = boundary_credential_store_vault.foo.id
|
credential_store_id = boundary_credential_store_vault.foo.id
|
||||||
path = "my/secret/foo" # change to Vault backend path
|
path = "my/secret/foo" # change to Vault backend path
|
||||||
http_method = "GET"
|
http_method = "GET"
|
||||||
|
credential_type = "username_password"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "boundary_host_catalog" "foo" {
|
resource "boundary_host_catalog" "foo" {
|
||||||
@@ -92,7 +93,21 @@ resource "boundary_target" "foo" {
|
|||||||
host_source_ids = [
|
host_source_ids = [
|
||||||
boundary_host_set.foo.id
|
boundary_host_set.foo.id
|
||||||
]
|
]
|
||||||
application_credential_source_ids = [
|
brokered_credential_source_ids = [
|
||||||
|
boundary_credential_library_vault.foo.id
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_target" "ssh_foo" {
|
||||||
|
name = "ssh_foo"
|
||||||
|
description = "Ssh target"
|
||||||
|
type = "ssh"
|
||||||
|
default_port = "22"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
host_source_ids = [
|
||||||
|
boundary_host_set.foo.id
|
||||||
|
]
|
||||||
|
injected_application_credential_source_ids = [
|
||||||
boundary_credential_library_vault.foo.id
|
boundary_credential_library_vault.foo.id
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -108,10 +123,11 @@ resource "boundary_target" "foo" {
|
|||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
- `application_credential_source_ids` (Set of String) A list of application credential source ID's.
|
- `brokered_credential_source_ids` (Set of String) A list of brokered credential source ID's.
|
||||||
- `default_port` (Number) The default port for this target.
|
- `default_port` (Number) The default port for this target.
|
||||||
- `description` (String) The target description.
|
- `description` (String) The target description.
|
||||||
- `host_source_ids` (Set of String) A list of host source ID's.
|
- `host_source_ids` (Set of String) A list of host source ID's.
|
||||||
|
- `injected_application_credential_source_ids` (Set of String) A list of injected application credential source ID's.
|
||||||
- `name` (String) The target name. Defaults to the resource name.
|
- `name` (String) The target name. Defaults to the resource name.
|
||||||
- `session_connection_limit` (Number)
|
- `session_connection_limit` (Number)
|
||||||
- `session_max_seconds` (Number)
|
- `session_max_seconds` (Number)
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_credential_json.example_json <my-id>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_json" "example" {
|
||||||
|
name = "example_json"
|
||||||
|
description = "My first json credential!"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
object = file("~/object.json") # change to valid json file
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_credential_ssh_private_key.example_ssh_private_key <my-id>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_ssh_private_key" "example" {
|
||||||
|
name = "example_ssh_private_key"
|
||||||
|
description = "My first ssh private key credential!"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
username = "my-username"
|
||||||
|
private_key = file("~/.ssh/id_rsa") # change to valid SSH Private Key
|
||||||
|
private_key_passphrase = "optional-passphrase" # change to the passphrase of the Private Key if required
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_credential_store_static.example_static_credential_store <my-id>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_credential_username_password.example_username_password <my-id>
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "global scope"
|
||||||
|
scope_id = "global"
|
||||||
|
auto_create_admin_role = true
|
||||||
|
auto_create_default_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_scope" "project" {
|
||||||
|
name = "project_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
auto_create_admin_role = true
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "example_static_credential_store"
|
||||||
|
description = "My first static credential store!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_username_password" "example" {
|
||||||
|
name = "example_username_password"
|
||||||
|
description = "My first username password credential!"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
username = "my-username"
|
||||||
|
password = "my-password"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_host_catalog_plugin.foo <my-id>
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.global.id
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the aws plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-aws
|
||||||
|
#
|
||||||
|
# For more information about aws users, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/aws-host-catalogs?in=boundary/oss-access-management#configure-terraform-and-iam-user-privileges
|
||||||
|
resource "boundary_host_catalog_plugin" "aws_example" {
|
||||||
|
name = "My aws catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "aws"
|
||||||
|
attributes_json = jsonencode({ "region" = "us-east-1" })
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in aws by creating a aws iam user with programmatic access
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"access_key_id" = "aws_access_key_id_value",
|
||||||
|
"secret_access_key" = "aws_secret_access_key_value"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the azure plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-azure
|
||||||
|
#
|
||||||
|
# For more information about azure ad applications, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/azure-host-catalogs#register-a-new-azure-ad-application-1
|
||||||
|
resource "boundary_host_catalog_plugin" "azure_example" {
|
||||||
|
name = "My azure catalog"
|
||||||
|
description = "My second host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "azure"
|
||||||
|
|
||||||
|
# the attributes below must be generated in azure by creating an ad application
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"disable_credential_rotation" = "true",
|
||||||
|
"tenant_id" = "ARM_TENANT_ID",
|
||||||
|
"subscription_id" = "ARM_SUBSCRIPTION_ID",
|
||||||
|
"client_id" = "ARM_CLIENT_ID"
|
||||||
|
})
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in azure by creating an ad application
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"secret_value" = "ARM_CLIENT_SECRET"
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_host_catalog_static.foo <my-id>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
resource "boundary_scope" "org" {
|
||||||
|
name = "organization_one"
|
||||||
|
description = "My first scope!"
|
||||||
|
scope_id = boundary_scope.global.id
|
||||||
|
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_host_catalog_static" "example" {
|
||||||
|
name = "My catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_host_set_plugin.foo <my-id>
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the aws plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-aws
|
||||||
|
#
|
||||||
|
# For more information about aws users, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/aws-host-catalogs?in=boundary/oss-access-management#configure-terraform-and-iam-user-privileges
|
||||||
|
resource "boundary_host_catalog_plugin" "aws_example" {
|
||||||
|
name = "My aws catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "aws"
|
||||||
|
attributes_json = jsonencode({ "region" = "us-east-1" })
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in aws by creating a aws iam user with programmatic access
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"access_key_id" = "aws_access_key_id_value",
|
||||||
|
"secret_access_key" = "aws_secret_access_key_value"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "web" {
|
||||||
|
name = "My web host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.aws_exmaple.id
|
||||||
|
attributes_json = jsonencode({ "filters" = "tag:service-type=web" })
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "foobar" {
|
||||||
|
name = "My foobar host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.aws_exmaple.id
|
||||||
|
preferred_endpoints = ["cidr:54.0.0.0/8"]
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"filters" = "tag-key=foo",
|
||||||
|
"filters" = "tag-key=bar"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "launch" {
|
||||||
|
name = "My launch host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.aws_exmaple.id
|
||||||
|
sync_interval_seconds = 60
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"filters" = "tag:development=prod,dev",
|
||||||
|
"filters" = "launch-time=2022-01-04T*"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
# For more information about the azure plugin, please visit here:
|
||||||
|
# https://github.com/hashicorp/boundary-plugin-host-azure
|
||||||
|
#
|
||||||
|
# For more information about azure ad applications, please visit here:
|
||||||
|
# https://learn.hashicorp.com/tutorials/boundary/azure-host-catalogs#register-a-new-azure-ad-application-1
|
||||||
|
resource "boundary_host_catalog_plugin" "azure_example" {
|
||||||
|
name = "My azure catalog"
|
||||||
|
description = "My second host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
plugin_name = "azure"
|
||||||
|
|
||||||
|
# the attributes below must be generated in azure by creating an ad application
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"disable_credential_rotation" = "true",
|
||||||
|
"tenant_id" = "ARM_TENANT_ID",
|
||||||
|
"subscription_id" = "ARM_SUBSCRIPTION_ID",
|
||||||
|
"client_id" = "ARM_CLIENT_ID"
|
||||||
|
})
|
||||||
|
|
||||||
|
# recommended to pass in aws secrets using a file() or using environment variables
|
||||||
|
# the secrets below must be generated in azure by creating an ad application
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"secret_value" = "ARM_CLIENT_SECRET"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "database" {
|
||||||
|
name = "My database host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.azure_exmaple.id
|
||||||
|
attributes_json = jsonencode({ "filter" = "tagName eq 'service-type' and tagValue eq 'database'" })
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_plugin" "foodev" {
|
||||||
|
name = "My foodev host set plugin"
|
||||||
|
host_catalog_id = boundary_host_catalog_plugin.azure_exmaple.id
|
||||||
|
preferred_endpoints = ["cidr:54.0.0.0/8"]
|
||||||
|
sync_interval_seconds = 60
|
||||||
|
attributes_json = jsonencode({
|
||||||
|
"filter" = "tagName eq 'tag-key' and tagValue eq 'foo'",
|
||||||
|
"filter" = "tagName eq 'application' and tagValue eq 'dev'",
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_host_set_static.foo <my-id>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
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_host_catalog_static" "example" {
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_static" "first" {
|
||||||
|
name = "host_1"
|
||||||
|
description = "My first host!"
|
||||||
|
address = "10.0.0.1"
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_static" "second" {
|
||||||
|
name = "host_2"
|
||||||
|
description = "My second host!"
|
||||||
|
address = "10.0.0.2"
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_set_static" "web" {
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
host_ids = [
|
||||||
|
boundary_host_static.first.id,
|
||||||
|
boundary_host_static.second.id,
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
terraform import boundary_host_static.foo <my-id>
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
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_host_catalog_static" "example" {
|
||||||
|
name = "My catalog"
|
||||||
|
description = "My first host catalog!"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_host_static" "example" {
|
||||||
|
name = "example_host"
|
||||||
|
description = "My first host!"
|
||||||
|
address = "10.0.0.1"
|
||||||
|
host_catalog_id = boundary_host_catalog_static.example.id
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ resource "boundary_credential_library_vault" "foo" {
|
|||||||
credential_store_id = boundary_credential_store_vault.foo.id
|
credential_store_id = boundary_credential_store_vault.foo.id
|
||||||
path = "my/secret/foo" # change to Vault backend path
|
path = "my/secret/foo" # change to Vault backend path
|
||||||
http_method = "GET"
|
http_method = "GET"
|
||||||
|
credential_type = "username_password"
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "boundary_host_catalog" "foo" {
|
resource "boundary_host_catalog" "foo" {
|
||||||
@@ -77,7 +78,21 @@ resource "boundary_target" "foo" {
|
|||||||
host_source_ids = [
|
host_source_ids = [
|
||||||
boundary_host_set.foo.id
|
boundary_host_set.foo.id
|
||||||
]
|
]
|
||||||
application_credential_source_ids = [
|
brokered_credential_source_ids = [
|
||||||
|
boundary_credential_library_vault.foo.id
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_target" "ssh_foo" {
|
||||||
|
name = "ssh_foo"
|
||||||
|
description = "Ssh target"
|
||||||
|
type = "ssh"
|
||||||
|
default_port = "22"
|
||||||
|
scope_id = boundary_scope.project.id
|
||||||
|
host_source_ids = [
|
||||||
|
boundary_host_set.foo.id
|
||||||
|
]
|
||||||
|
injected_application_credential_source_ids = [
|
||||||
boundary_credential_library_vault.foo.id
|
boundary_credential_library_vault.foo.id
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,32 +1,33 @@
|
|||||||
module github.com/hashicorp/terraform-provider-boundary
|
module github.com/hashicorp/terraform-provider-boundary
|
||||||
|
|
||||||
go 1.18
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/hashicorp/boundary v0.8.1
|
github.com/hashicorp/boundary v0.11.0
|
||||||
github.com/hashicorp/boundary/api v0.0.24
|
github.com/hashicorp/boundary/api v0.0.30
|
||||||
github.com/hashicorp/boundary/sdk v0.0.15
|
github.com/hashicorp/boundary/sdk v0.0.24
|
||||||
github.com/hashicorp/cap v0.2.0
|
github.com/hashicorp/cap v0.2.0
|
||||||
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637
|
github.com/hashicorp/go-cty v1.4.1-0.20200723130312-85980079f637
|
||||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.5
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.6-0.20220722192355-a843f53fa48d
|
||||||
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.3
|
github.com/hashicorp/go-secure-stdlib/configutil/v2 v2.0.5
|
||||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.5
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7
|
||||||
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.1
|
github.com/hashicorp/go-secure-stdlib/pluginutil/v2 v2.0.3
|
||||||
github.com/hashicorp/terraform-plugin-docs v0.9.0
|
github.com/hashicorp/terraform-plugin-docs v0.13.0
|
||||||
github.com/hashicorp/terraform-plugin-sdk/v2 v2.17.0
|
github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0
|
||||||
github.com/kr/pretty v0.3.0
|
github.com/kr/pretty v0.3.1
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/stretchr/testify v1.7.1
|
github.com/stretchr/testify v1.8.0
|
||||||
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
|
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||||
|
github.com/DATA-DOG/go-sqlmock v1.5.0 // indirect
|
||||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||||
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
|
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
|
||||||
github.com/Microsoft/go-winio v0.4.16 // indirect
|
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
|
||||||
github.com/agext/levenshtein v1.2.2 // indirect
|
github.com/agext/levenshtein v1.2.2 // indirect
|
||||||
github.com/alessio/shellescape v1.4.1 // indirect
|
github.com/alessio/shellescape v1.4.1 // indirect
|
||||||
@@ -38,13 +39,12 @@ require (
|
|||||||
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.1.0 // indirect
|
github.com/cenkalti/backoff/v4 v4.1.0 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||||
github.com/containerd/containerd v1.4.3 // indirect
|
github.com/containerd/continuity v0.1.0 // indirect
|
||||||
github.com/containerd/continuity v0.0.0-20200709052629-daa8e1ccc0bc // indirect
|
|
||||||
github.com/coreos/go-oidc/v3 v3.1.0 // indirect
|
github.com/coreos/go-oidc/v3 v3.1.0 // indirect
|
||||||
github.com/danieljoos/wincred v1.1.2 // indirect
|
github.com/danieljoos/wincred v1.1.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/docker/cli v20.10.7+incompatible // indirect
|
github.com/docker/cli v20.10.7+incompatible // indirect
|
||||||
github.com/docker/docker v20.10.7+incompatible // indirect
|
github.com/docker/docker v20.10.9+incompatible // indirect
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/docker/go-units v0.4.0 // indirect
|
github.com/docker/go-units v0.4.0 // indirect
|
||||||
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
github.com/dvsekhvalnov/jose2go v1.5.0 // indirect
|
||||||
@@ -52,14 +52,14 @@ require (
|
|||||||
github.com/fatih/structs v1.1.0 // indirect
|
github.com/fatih/structs v1.1.0 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.0.6 // indirect
|
github.com/godbus/dbus/v5 v5.0.6 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-migrate/migrate/v4 v4.14.1 // indirect
|
github.com/golang-migrate/migrate/v4 v4.15.1 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-cmp v0.5.8 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.10.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 // indirect
|
||||||
github.com/hashicorp/dbassert v0.0.0-20210708202608-ecf920cf1ed8 // indirect
|
github.com/hashicorp/dbassert v0.0.0-20210708202608-ecf920cf1ed8 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/eventlogger v0.1.1-0.20211106154408-4ff8da3a890c // indirect
|
github.com/hashicorp/eventlogger v0.1.1-0.20211106154408-4ff8da3a890c // indirect
|
||||||
@@ -67,9 +67,10 @@ require (
|
|||||||
github.com/hashicorp/go-bexpr v0.1.10 // indirect
|
github.com/hashicorp/go-bexpr v0.1.10 // indirect
|
||||||
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
github.com/hashicorp/go-checkpoint v0.5.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-dbw v0.0.0-20211215222256-2ff0d37184ff // indirect
|
github.com/hashicorp/go-dbw v0.0.0-20220725170111-b7cb3aa3d628 // indirect
|
||||||
github.com/hashicorp/go-hclog v1.2.0 // indirect
|
github.com/hashicorp/go-hclog v1.2.2 // indirect
|
||||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||||
|
github.com/hashicorp/go-kms-wrapping/extras/kms/v2 v2.0.0-20220711120347-32232bae6803 // indirect
|
||||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2 // indirect
|
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-plugin v1.4.4 // indirect
|
github.com/hashicorp/go-plugin v1.4.4 // indirect
|
||||||
@@ -85,17 +86,18 @@ require (
|
|||||||
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1 // indirect
|
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1 // indirect
|
||||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
github.com/hashicorp/go-uuid v1.0.3 // indirect
|
||||||
github.com/hashicorp/go-version v1.5.0 // indirect
|
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||||
github.com/hashicorp/hc-install v0.3.2 // indirect
|
github.com/hashicorp/hc-install v0.4.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/hashicorp/hcl/v2 v2.12.0 // indirect
|
github.com/hashicorp/hcl/v2 v2.14.0 // indirect
|
||||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||||
github.com/hashicorp/terraform-exec v0.16.1 // indirect
|
github.com/hashicorp/nodeenrollment v0.1.17 // indirect
|
||||||
|
github.com/hashicorp/terraform-exec v0.17.3 // indirect
|
||||||
github.com/hashicorp/terraform-json v0.14.0 // indirect
|
github.com/hashicorp/terraform-json v0.14.0 // indirect
|
||||||
github.com/hashicorp/terraform-plugin-go v0.9.1 // indirect
|
github.com/hashicorp/terraform-plugin-go v0.14.0 // indirect
|
||||||
github.com/hashicorp/terraform-plugin-log v0.4.0 // indirect
|
github.com/hashicorp/terraform-plugin-log v0.7.0 // indirect
|
||||||
github.com/hashicorp/terraform-registry-address v0.0.0-20210412075316-9b2996cce896 // indirect
|
github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c // indirect
|
||||||
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
|
github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 // indirect
|
||||||
github.com/hashicorp/vault/api v1.3.1 // indirect
|
github.com/hashicorp/vault/api v1.3.1 // indirect
|
||||||
github.com/hashicorp/vault/sdk v0.3.0 // indirect
|
github.com/hashicorp/vault/sdk v0.3.0 // indirect
|
||||||
@@ -103,25 +105,25 @@ require (
|
|||||||
github.com/huandu/xstrings v1.3.2 // indirect
|
github.com/huandu/xstrings v1.3.2 // indirect
|
||||||
github.com/imdario/mergo v0.3.13 // indirect
|
github.com/imdario/mergo v0.3.13 // indirect
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
|
||||||
github.com/jackc/pgconn v1.10.1 // indirect
|
github.com/jackc/pgconn v1.12.1 // indirect
|
||||||
github.com/jackc/pgio v1.0.0 // indirect
|
github.com/jackc/pgio v1.0.0 // indirect
|
||||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/jackc/pgproto3/v2 v2.2.0 // indirect
|
github.com/jackc/pgproto3/v2 v2.3.0 // indirect
|
||||||
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
|
||||||
github.com/jackc/pgtype v1.9.0 // indirect
|
github.com/jackc/pgtype v1.11.0 // indirect
|
||||||
github.com/jackc/pgx/v4 v4.14.0 // indirect
|
github.com/jackc/pgx/v4 v4.16.1 // indirect
|
||||||
github.com/jefferai/go-libsecret v0.0.0-20210525195240-b53481abef97 // indirect
|
github.com/jefferai/go-libsecret v0.0.0-20210525195240-b53481abef97 // indirect
|
||||||
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f // indirect
|
github.com/jefferai/isbadcipher v0.0.0-20190226160619-51d2077c035f // indirect
|
||||||
github.com/jefferai/keyring v1.1.7-0.20220316160357-58a74bb55891 // indirect
|
github.com/jefferai/keyring v1.1.7-0.20220316160357-58a74bb55891 // indirect
|
||||||
github.com/jinzhu/gorm v1.9.12 // indirect
|
github.com/jinzhu/gorm v1.9.12 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.3 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/lib/pq v1.10.2 // indirect
|
github.com/lib/pq v1.10.2 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.12 // indirect
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mattn/go-sqlite3 v2.0.1+incompatible // indirect
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
|
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||||
github.com/mitchellh/cli v1.1.4 // indirect
|
github.com/mitchellh/cli v1.1.4 // indirect
|
||||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
|
||||||
@@ -129,13 +131,13 @@ require (
|
|||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
github.com/mitchellh/pointerstructure v1.2.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/moby/term v0.0.0-20201216013528-df9cb8a40635 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||||
github.com/mtibben/percent v0.2.1 // indirect
|
github.com/mtibben/percent v0.2.1 // indirect
|
||||||
github.com/oklog/run v1.0.0 // indirect
|
github.com/oklog/run v1.0.0 // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.1 // indirect
|
github.com/opencontainers/image-spec v1.0.1 // indirect
|
||||||
github.com/opencontainers/runc v1.0.0-rc9 // indirect
|
github.com/opencontainers/runc v1.0.2 // indirect
|
||||||
github.com/ory/dockertest/v3 v3.7.0 // indirect
|
github.com/ory/dockertest/v3 v3.7.0 // indirect
|
||||||
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
github.com/pires/go-proxyproto v0.6.1 // indirect
|
github.com/pires/go-proxyproto v0.6.1 // indirect
|
||||||
@@ -146,11 +148,12 @@ require (
|
|||||||
github.com/prometheus/client_model v0.2.0 // indirect
|
github.com/prometheus/client_model v0.2.0 // indirect
|
||||||
github.com/prometheus/common v0.32.1 // indirect
|
github.com/prometheus/common v0.32.1 // indirect
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
github.com/prometheus/procfs v0.7.3 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||||
github.com/russross/blackfriday v1.6.0 // indirect
|
github.com/russross/blackfriday v1.6.0 // indirect
|
||||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||||
|
github.com/sethvargo/go-diceware v0.3.0 // indirect
|
||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/sirupsen/logrus v1.7.0 // indirect
|
github.com/sirupsen/logrus v1.8.1 // indirect
|
||||||
github.com/spf13/cast v1.5.0 // indirect
|
github.com/spf13/cast v1.5.0 // indirect
|
||||||
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
github.com/vmihailenco/msgpack v4.0.4+incompatible // indirect
|
||||||
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
github.com/vmihailenco/msgpack/v4 v4.3.12 // indirect
|
||||||
@@ -158,24 +161,24 @@ require (
|
|||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||||
github.com/xo/dburl v0.9.0 // indirect
|
github.com/xo/dburl v0.11.0 // indirect
|
||||||
github.com/zalando/go-keyring v0.2.1 // indirect
|
github.com/zalando/go-keyring v0.2.1 // indirect
|
||||||
github.com/zclconf/go-cty v1.10.0 // indirect
|
github.com/zclconf/go-cty v1.11.0 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect
|
golang.org/x/oauth2 v0.0.0-20220722155238-128564f6959c // indirect
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b // indirect
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
|
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220317150908-0efb43f6373e // indirect
|
google.golang.org/genproto v0.0.0-20220805133916-01dd62135a58 // indirect
|
||||||
google.golang.org/grpc v1.46.0 // indirect
|
google.golang.org/grpc v1.48.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.0 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
gorm.io/driver/postgres v1.2.2 // indirect
|
gorm.io/driver/postgres v1.3.8 // indirect
|
||||||
gorm.io/driver/sqlite v1.2.4 // indirect
|
gorm.io/driver/sqlite v1.3.6 // indirect
|
||||||
gorm.io/gorm v1.22.3 // indirect
|
gorm.io/gorm v1.23.8 // indirect
|
||||||
)
|
)
|
||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
|
"github.com/hashicorp/go-secure-stdlib/pluginutil/v2"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/hashicorp/terraform-provider-boundary/plugins/kms"
|
kms_plugin_assets "github.com/hashicorp/terraform-provider-boundary/plugins/kms"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -60,30 +60,39 @@ func New() *schema.Provider {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
Description: "When set to true, does not validate the Boundary API endpoint certificate",
|
Description: "When set to true, does not validate the Boundary API endpoint certificate",
|
||||||
},
|
},
|
||||||
|
"plugin_execution_dir": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Description: `Specifies a directory that the Boundary provider can use to write and execute its built-in plugins.`,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
"boundary_account": resourceAccount(),
|
"boundary_account": resourceAccount(),
|
||||||
"boundary_account_password": resourceAccountPassword(),
|
"boundary_account_password": resourceAccountPassword(),
|
||||||
"boundary_account_oidc": resourceAccountOidc(),
|
"boundary_account_oidc": resourceAccountOidc(),
|
||||||
"boundary_auth_method": resourceAuthMethod(),
|
"boundary_auth_method": resourceAuthMethod(),
|
||||||
"boundary_auth_method_password": resourceAuthMethodPassword(),
|
"boundary_auth_method_password": resourceAuthMethodPassword(),
|
||||||
"boundary_auth_method_oidc": resourceAuthMethodOidc(),
|
"boundary_auth_method_oidc": resourceAuthMethodOidc(),
|
||||||
"boundary_credential_library_vault": resourceCredentialLibraryVault(),
|
"boundary_credential_library_vault": resourceCredentialLibraryVault(),
|
||||||
"boundary_credential_store_vault": resourceCredentialStoreVault(),
|
"boundary_credential_store_vault": resourceCredentialStoreVault(),
|
||||||
"boundary_managed_group": resourceManagedGroup(),
|
"boundary_credential_store_static": resourceCredentialStoreStatic(),
|
||||||
"boundary_group": resourceGroup(),
|
"boundary_credential_username_password": resourceCredentialUsernamePassword(),
|
||||||
"boundary_host": resourceHost(),
|
"boundary_credential_ssh_private_key": resourceCredentialSshPrivateKey(),
|
||||||
"boundary_host_static": resourceHostStatic(),
|
"boundary_credential_json": resourceCredentialJson(),
|
||||||
"boundary_host_catalog": resourceHostCatalog(),
|
"boundary_managed_group": resourceManagedGroup(),
|
||||||
"boundary_host_catalog_static": resourceHostCatalogStatic(),
|
"boundary_group": resourceGroup(),
|
||||||
"boundary_host_catalog_plugin": resourceHostCatalogPlugin(),
|
"boundary_host": resourceHost(),
|
||||||
"boundary_host_set": resourceHostSet(),
|
"boundary_host_static": resourceHostStatic(),
|
||||||
"boundary_host_set_static": resourceHostSetStatic(),
|
"boundary_host_catalog": resourceHostCatalog(),
|
||||||
"boundary_host_set_plugin": resourceHostSetPlugin(),
|
"boundary_host_catalog_static": resourceHostCatalogStatic(),
|
||||||
"boundary_role": resourceRole(),
|
"boundary_host_catalog_plugin": resourceHostCatalogPlugin(),
|
||||||
"boundary_scope": resourceScope(),
|
"boundary_host_set": resourceHostSet(),
|
||||||
"boundary_target": resourceTarget(),
|
"boundary_host_set_static": resourceHostSetStatic(),
|
||||||
"boundary_user": resourceUser(),
|
"boundary_host_set_plugin": resourceHostSetPlugin(),
|
||||||
|
"boundary_role": resourceRole(),
|
||||||
|
"boundary_scope": resourceScope(),
|
||||||
|
"boundary_target": resourceTarget(),
|
||||||
|
"boundary_user": resourceUser(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,11 +121,22 @@ func providerAuthenticate(ctx context.Context, d *schema.ResourceData, md *metaD
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(`error reading data from "recovery_kms_hcl": %v`, err)
|
return fmt.Errorf(`error reading data from "recovery_kms_hcl": %v`, err)
|
||||||
}
|
}
|
||||||
wrapper, _, err := wrapper.GetWrapperFromHcl(ctx, recoveryHclStr, "recovery",
|
|
||||||
configutil.WithPluginOptions(
|
opts := []pluginutil.Option{
|
||||||
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
pluginutil.WithPluginsMap(kms_plugin_assets.BuiltinKmsPlugins()),
|
||||||
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
pluginutil.WithPluginsFilesystem(kms_plugin_assets.KmsPluginPrefix, kms_plugin_assets.FileSystem()),
|
||||||
))
|
}
|
||||||
|
|
||||||
|
if execDir, ok := d.GetOk("plugin_execution_dir"); ok {
|
||||||
|
opts = append(opts, pluginutil.WithPluginExecutionDirectory(execDir.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: cleanup plugin when finished
|
||||||
|
wrapper, _, err := wrapper.GetWrapperFromHcl(
|
||||||
|
ctx,
|
||||||
|
recoveryHclStr,
|
||||||
|
"recovery",
|
||||||
|
configutil.WithPluginOptions(opts...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf(`error reading wrappers from "recovery_kms_hcl": %v`, err)
|
return fmt.Errorf(`error reading wrappers from "recovery_kms_hcl": %v`, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import (
|
|||||||
|
|
||||||
func resourceAccount() *schema.Resource {
|
func resourceAccount() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
DeprecationMessage: "Deprecated: use `resource_account_password` instead.",
|
DeprecationMessage: "Deprecated: use `boundary_account_password` instead.",
|
||||||
Description: "Deprecated: use `resource_account_password` instead.",
|
Description: "Deprecated: use `boundary_account_password` instead.",
|
||||||
|
|
||||||
CreateContext: resourceAccountCreate,
|
CreateContext: resourceAccountCreate,
|
||||||
ReadContext: resourceAccountRead,
|
ReadContext: resourceAccountRead,
|
||||||
@@ -60,7 +60,7 @@ func resourceAccount() *schema.Resource {
|
|||||||
Description: "The account password. Only set on create, changes will not be reflected when updating account.",
|
Description: "The account password. Only set on create, changes will not be reflected when updating account.",
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
||||||
if d.Id() == "" {
|
if d.Id() == "" {
|
||||||
// This is a new resource do not suppress password diff
|
// This is a new resource do not suppress password diff
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ func resourceAccountPassword() *schema.Resource {
|
|||||||
Description: "The account password. Only set on create, changes will not be reflected when updating account.",
|
Description: "The account password. Only set on create, changes will not be reflected when updating account.",
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
|
||||||
if d.Id() == "" {
|
if d.Id() == "" {
|
||||||
// This is a new resource do not suppress password diff
|
// This is a new resource do not suppress password diff
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ func resourceAuthMethodOidc() *schema.Resource {
|
|||||||
Description: "The secret key assigned to this auth method from the provider. Once set, only the hash will be kept and the original value can be removed from configuration.",
|
Description: "The secret key assigned to this auth method from the provider. Once set, only the hash will be kept and the original value can be removed from configuration.",
|
||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
},
|
},
|
||||||
authmethodOidcIssuerKey: {
|
authmethodOidcIssuerKey: {
|
||||||
Description: "The issuer corresponding to the provider, which must match the issuer field in generated tokens.",
|
Description: "The issuer corresponding to the provider, which must match the issuer field in generated tokens.",
|
||||||
|
|||||||
@@ -0,0 +1,222 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentials"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
credentialJsonCredentialType = "json"
|
||||||
|
credentialJsonObjectKey = "object"
|
||||||
|
credentialJsonObjectHmacKey = "object_hmac"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceCredentialJson() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Description: "The json credential resource allows you to congiure a credential using a json object.",
|
||||||
|
|
||||||
|
CreateContext: resourceCredentialJsonCreate,
|
||||||
|
ReadContext: resourceCredentialJsonRead,
|
||||||
|
UpdateContext: resourceCredentialJsonUpdate,
|
||||||
|
DeleteContext: resourceCredentialJsonDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
StateContext: schema.ImportStatePassthroughContext,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
IDKey: {
|
||||||
|
Description: "The ID of this json credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
NameKey: {
|
||||||
|
Description: "The name of this json credential. Defaults to the resource name.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
DescriptionKey: {
|
||||||
|
Description: "The description of this json credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
credentialStoreIdKey: {
|
||||||
|
Description: "The credential store in which to save this json credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
ForceNew: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
credentialJsonObjectKey: {
|
||||||
|
Description: `The object for the this json credential. Either values encoded with the "jsonencode" function, pre-escaped JSON string, or a file`,
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
credentialJsonObjectHmacKey: {
|
||||||
|
Description: "The object hmac.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFromCredentialJsonResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||||
|
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if attrsVal, ok := raw["attributes"]; ok {
|
||||||
|
attrs := attrsVal.(map[string]interface{})
|
||||||
|
stateObjectHmac := d.Get(credentialJsonObjectHmacKey)
|
||||||
|
boundaryObjectHmac := attrs[credentialJsonObjectHmacKey].(string)
|
||||||
|
if stateObjectHmac.(string) != boundaryObjectHmac && fromRead {
|
||||||
|
if err := d.Set(credentialJsonObjectKey, "(changed in Boundary)"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialJsonObjectHmacKey, boundaryObjectHmac); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(raw["id"].(string))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialJsonCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
|
||||||
|
var opts []credentials.Option
|
||||||
|
if v, ok := d.GetOk(NameKey); ok {
|
||||||
|
opts = append(opts, credentials.WithName(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||||
|
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
if v, ok := d.GetOk(credentialJsonObjectKey); ok {
|
||||||
|
var jsonObject map[string]interface{}
|
||||||
|
if err := json.Unmarshal([]byte(v.(string)), &jsonObject); err != nil {
|
||||||
|
return diag.Errorf("error unmarshaling json: %v", err)
|
||||||
|
}
|
||||||
|
opts = append(opts, credentials.WithJsonCredentialObject(jsonObject))
|
||||||
|
}
|
||||||
|
|
||||||
|
var credentialStoreId string
|
||||||
|
retrievedStoreId, ok := d.GetOk(credentialStoreIdKey)
|
||||||
|
if ok {
|
||||||
|
credentialStoreId = retrievedStoreId.(string)
|
||||||
|
} else {
|
||||||
|
return diag.Errorf("credential store id is unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
cred, err := client.Create(ctx, credentialJsonCredentialType, credentialStoreId, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error creating credential: %v", err)
|
||||||
|
}
|
||||||
|
if cred == nil {
|
||||||
|
return diag.Errorf("nil credential after create")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFromCredentialJsonResponseMap(d, cred.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialJsonRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
cred, err := client.Read(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return diag.Errorf("error reading credential: %v", err)
|
||||||
|
}
|
||||||
|
if cred == nil {
|
||||||
|
return diag.Errorf("credential nil after read")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFromCredentialJsonResponseMap(d, cred.GetResponse().Map, true); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialJsonUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
var opts []credentials.Option
|
||||||
|
if d.HasChange(NameKey) {
|
||||||
|
opts = append(opts, credentials.DefaultName())
|
||||||
|
if v, ok := d.GetOk(NameKey); ok {
|
||||||
|
opts = append(opts, credentials.WithName(v.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(DescriptionKey) {
|
||||||
|
opts = append(opts, credentials.DefaultDescription())
|
||||||
|
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||||
|
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(credentialJsonObjectKey) {
|
||||||
|
if v, ok := d.GetOk(credentialJsonObjectKey); ok {
|
||||||
|
var jsonObject map[string]interface{}
|
||||||
|
if err := json.Unmarshal([]byte(v.(string)), &jsonObject); err != nil {
|
||||||
|
return diag.Errorf("error unmarshaling json: %v", err)
|
||||||
|
}
|
||||||
|
opts = append(opts, credentials.WithJsonCredentialObject(jsonObject))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts) > 0 {
|
||||||
|
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||||
|
credUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error updating credential: %v", err)
|
||||||
|
}
|
||||||
|
if credUpdate == nil {
|
||||||
|
return diag.Errorf("credential nil after update")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = setFromCredentialJsonResponseMap(d, credUpdate.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialJsonDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
_, err := client.Delete(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error deleting credential: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentials"
|
||||||
|
"github.com/hashicorp/boundary/testing/controller"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
jsonCredResc = "boundary_credential_json.example"
|
||||||
|
jsonCredName = "bar"
|
||||||
|
jsonCredNameUpdate = "foo"
|
||||||
|
jsonCredDesc = "the bar"
|
||||||
|
jsonCredDescUpdate = "the foo"
|
||||||
|
jsonCredObj = `jsonencode({
|
||||||
|
password = "password",
|
||||||
|
username = "admin"
|
||||||
|
})`
|
||||||
|
jsonCredObjUpdate = `jsonencode({
|
||||||
|
password = "password",
|
||||||
|
username = "db-admin"
|
||||||
|
})`
|
||||||
|
)
|
||||||
|
|
||||||
|
func jsonCredResource(name, description, object string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "static store name"
|
||||||
|
description = "static store description"
|
||||||
|
scope_id = boundary_scope.proj1.id
|
||||||
|
depends_on = [boundary_role.proj1_admin]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_json" "example" {
|
||||||
|
name = "%s"
|
||||||
|
description = "%s"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
object = %s
|
||||||
|
}`, name, description, object)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccCredentialJson(t *testing.T) {
|
||||||
|
tc := controller.NewTestController(t, tcConfig...)
|
||||||
|
defer tc.Shutdown()
|
||||||
|
url := tc.ApiAddrs()[0]
|
||||||
|
|
||||||
|
res := jsonCredResource(
|
||||||
|
jsonCredName,
|
||||||
|
jsonCredDesc,
|
||||||
|
jsonCredObj,
|
||||||
|
)
|
||||||
|
|
||||||
|
resUpdate := jsonCredResource(
|
||||||
|
jsonCredNameUpdate,
|
||||||
|
jsonCredDescUpdate,
|
||||||
|
jsonCredObjUpdate,
|
||||||
|
)
|
||||||
|
|
||||||
|
var provider *schema.Provider
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
ProviderFactories: providerFactories(&provider),
|
||||||
|
CheckDestroy: testAccCheckCredentialJsonResourceDestroy(t, provider),
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
// create
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(jsonCredResc, NameKey, jsonCredName),
|
||||||
|
resource.TestCheckResourceAttr(jsonCredResc, DescriptionKey, jsonCredDesc),
|
||||||
|
resource.TestCheckResourceAttr(jsonCredResc, credentialJsonObjectKey, `{"password":"password","username":"admin"}`),
|
||||||
|
|
||||||
|
testAccCheckCredentialJsonObjectHmac(provider),
|
||||||
|
testAccCheckCredentialJsonResourceExists(provider, jsonCredResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(jsonCredResc, credentialJsonObjectKey),
|
||||||
|
{
|
||||||
|
// update
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(jsonCredResc, NameKey, jsonCredNameUpdate),
|
||||||
|
resource.TestCheckResourceAttr(jsonCredResc, DescriptionKey, jsonCredDescUpdate),
|
||||||
|
resource.TestCheckResourceAttr(jsonCredResc, credentialJsonObjectKey, `{"password":"password","username":"db-admin"}`),
|
||||||
|
|
||||||
|
testAccCheckCredentialJsonObjectHmac(provider),
|
||||||
|
testAccCheckCredentialJsonResourceExists(provider, jsonCredResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(jsonCredResc, credentialJsonObjectKey),
|
||||||
|
{
|
||||||
|
// Run a plan only update and verify no changes
|
||||||
|
PlanOnly: true,
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
},
|
||||||
|
importStep(jsonCredResc, credentialJsonObjectKey),
|
||||||
|
{
|
||||||
|
// update again but apply a preConfig to externally update resource
|
||||||
|
PreConfig: func() { jsonCredExternalUpdate(t, provider) },
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
},
|
||||||
|
importStep(jsonCredResc, credentialJsonObjectKey),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialJsonResourceDestroy(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_json":
|
||||||
|
id := rs.Primary.ID
|
||||||
|
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
_, err := c.Read(context.Background(), id)
|
||||||
|
if apiErr := api.AsServerError(err); apiErr == nil || apiErr.Response().StatusCode() != http.StatusNotFound {
|
||||||
|
return fmt.Errorf("didn't get a 404 when reading destroyed json credential %q: %v", id, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialJsonResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := rs.Primary.ID
|
||||||
|
if id == "" {
|
||||||
|
return fmt.Errorf("no ID is set")
|
||||||
|
}
|
||||||
|
storeId = id
|
||||||
|
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
if _, err := c.Read(context.Background(), id); err != nil {
|
||||||
|
return fmt.Errorf("got an error reading %q: %w", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialJsonObjectHmac(testProvider *schema.Provider) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[jsonCredResc]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found: %s", jsonCredResc)
|
||||||
|
}
|
||||||
|
|
||||||
|
computed := rs.Primary.Attributes["object_hmac"]
|
||||||
|
if len(computed) != 43 {
|
||||||
|
return fmt.Errorf("Computed password hmac not the expected length of 43 characters. hmac: %q", computed)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func jsonCredExternalUpdate(t *testing.T, testProvider *schema.Provider) {
|
||||||
|
if storeId == "" {
|
||||||
|
t.Fatal("storeId must be set before testing an external update")
|
||||||
|
}
|
||||||
|
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
cr, err := c.Read(context.Background(), storeId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(fmt.Errorf("got an error reading %q: %w", storeId, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// update credential options
|
||||||
|
var opts []credentials.Option
|
||||||
|
opts = append(opts, credentials.WithDescription("this is an updated description"))
|
||||||
|
|
||||||
|
_, err = c.Update(context.Background(), cr.Item.Id, cr.Item.Version, opts...)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(fmt.Errorf("got an error updating %q: %w", cr.Item.Id, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/hashicorp/boundary/api"
|
"github.com/hashicorp/boundary/api"
|
||||||
"github.com/hashicorp/boundary/api/credentiallibraries"
|
"github.com/hashicorp/boundary/api/credentiallibraries"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
)
|
)
|
||||||
@@ -16,6 +15,7 @@ const (
|
|||||||
credentialLibraryVaultHttpMethodKey = "http_method"
|
credentialLibraryVaultHttpMethodKey = "http_method"
|
||||||
credentialLibraryVaultHttpRequestBodyKey = "http_request_body"
|
credentialLibraryVaultHttpRequestBodyKey = "http_request_body"
|
||||||
credentialLibraryVaultPathKey = "path"
|
credentialLibraryVaultPathKey = "path"
|
||||||
|
credentialLibraryCredentialTypeKey = "credential_type"
|
||||||
)
|
)
|
||||||
|
|
||||||
var libraryVaultAttrs = []string{
|
var libraryVaultAttrs = []string{
|
||||||
@@ -73,6 +73,11 @@ func resourceCredentialLibraryVault() *schema.Resource {
|
|||||||
Type: schema.TypeString,
|
Type: schema.TypeString,
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
|
credentialLibraryCredentialTypeKey: {
|
||||||
|
Description: "The type of credential the library generates.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,6 +126,9 @@ func resourceCredentialLibraryCreateVault(ctx context.Context, d *schema.Resourc
|
|||||||
if v, ok := d.GetOk(credentialLibraryVaultPathKey); ok {
|
if v, ok := d.GetOk(credentialLibraryVaultPathKey); ok {
|
||||||
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryPath(v.(string)))
|
opts = append(opts, credentiallibraries.WithVaultCredentialLibraryPath(v.(string)))
|
||||||
}
|
}
|
||||||
|
if v, ok := d.GetOk(credentialLibraryCredentialTypeKey); ok {
|
||||||
|
opts = append(opts, credentiallibraries.WithCredentialType(v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
var credentialStoreId string
|
var credentialStoreId string
|
||||||
cid, ok := d.GetOk(credentialStoreIdKey)
|
cid, ok := d.GetOk(credentialStoreIdKey)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
vaultCredResc = "boundary_credential_library_vault.example"
|
vaultCredResc = "boundary_credential_library_vault.example"
|
||||||
|
vaultCredTypedResc = "boundary_credential_library_vault.typed_example"
|
||||||
vaultCredLibName = "foo"
|
vaultCredLibName = "foo"
|
||||||
vaultCredLibDesc = "the foo"
|
vaultCredLibDesc = "the foo"
|
||||||
vaultCredLibPath = "/foo/bar"
|
vaultCredLibPath = "/foo/bar"
|
||||||
@@ -52,6 +53,19 @@ resource "boundary_credential_library_vault" "example" {
|
|||||||
vaultCredLibMethodPost,
|
vaultCredLibMethodPost,
|
||||||
vaultCredLibRequestBody)
|
vaultCredLibRequestBody)
|
||||||
|
|
||||||
|
var vaultTypedCredLibResource = fmt.Sprintf(`
|
||||||
|
resource "boundary_credential_library_vault" "typed_example" {
|
||||||
|
name = "%s"
|
||||||
|
description = "%s"
|
||||||
|
credential_store_id = boundary_credential_store_vault.example.id
|
||||||
|
path = "%s"
|
||||||
|
http_method = "%s"
|
||||||
|
credential_type = "ssh_private_key"
|
||||||
|
}`, vaultCredLibName,
|
||||||
|
vaultCredLibDesc,
|
||||||
|
vaultCredLibPath,
|
||||||
|
vaultCredLibMethodGet)
|
||||||
|
|
||||||
func TestAccCredentialLibraryVault(t *testing.T) {
|
func TestAccCredentialLibraryVault(t *testing.T) {
|
||||||
tc := controller.NewTestController(t, tcConfig...)
|
tc := controller.NewTestController(t, tcConfig...)
|
||||||
defer tc.Shutdown()
|
defer tc.Shutdown()
|
||||||
@@ -69,8 +83,9 @@ func TestAccCredentialLibraryVault(t *testing.T) {
|
|||||||
|
|
||||||
var provider *schema.Provider
|
var provider *schema.Provider
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
|
IsUnitTest: true,
|
||||||
ProviderFactories: providerFactories(&provider),
|
ProviderFactories: providerFactories(&provider),
|
||||||
CheckDestroy: testAccCheckAuthMethodResourceDestroy(t, provider),
|
CheckDestroy: testAccCheckCredentialLibraryVaultResourceDestroy(t, provider),
|
||||||
Steps: []resource.TestStep{
|
Steps: []resource.TestStep{
|
||||||
{
|
{
|
||||||
// create
|
// create
|
||||||
@@ -101,6 +116,22 @@ func TestAccCredentialLibraryVault(t *testing.T) {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
importStep(vaultCredResc),
|
importStep(vaultCredResc),
|
||||||
|
|
||||||
|
{
|
||||||
|
// create typed credential library, note credential type is immutable so no need for update test
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, credStoreRes, vaultCredLibResourceUpdate, vaultTypedCredLibResource),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(vaultCredTypedResc, NameKey, vaultCredLibName),
|
||||||
|
resource.TestCheckResourceAttr(vaultCredTypedResc, DescriptionKey, vaultCredLibDesc),
|
||||||
|
resource.TestCheckResourceAttr(vaultCredTypedResc, credentialLibraryVaultPathKey, vaultCredLibPath),
|
||||||
|
resource.TestCheckResourceAttr(vaultCredTypedResc, credentialLibraryVaultHttpMethodKey, vaultCredLibMethodGet),
|
||||||
|
resource.TestCheckResourceAttr(vaultCredTypedResc, credentialLibraryVaultHttpRequestBodyKey, ""),
|
||||||
|
resource.TestCheckResourceAttr(vaultCredTypedResc, credentialLibraryCredentialTypeKey, "ssh_private_key"),
|
||||||
|
|
||||||
|
testAccCheckCredentialLibraryVaultResourceExists(provider, vaultCredTypedResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(vaultCredResc),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,278 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentials"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
credentialSshPrivateKeyUsernameKey = "username"
|
||||||
|
credentialSshPrivateKeyPrivateKeyKey = "private_key"
|
||||||
|
credentialSshPrivateKeyPrivateKeyHmacKey = "private_key_hmac"
|
||||||
|
credentialSshPrivateKeyPassphraseKey = "private_key_passphrase"
|
||||||
|
credentialSshPrivateKeyPassphraseHmacKey = "private_key_passphrase_hmac"
|
||||||
|
credentialSshPrivateKeyCredentialType = "ssh_private_key"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceCredentialSshPrivateKey() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Description: "The SSH private key credential resource allows you to configure a credential using a username, private key and optional passphrase.",
|
||||||
|
|
||||||
|
CreateContext: resourceCredentialSshPrivateKeyCreate,
|
||||||
|
ReadContext: resourceCredentialSshPrivateKeyRead,
|
||||||
|
UpdateContext: resourceCredentialSshPrivateKeyUpdate,
|
||||||
|
DeleteContext: resourceCredentialSshPrivateKeyDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
StateContext: schema.ImportStatePassthroughContext,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
IDKey: {
|
||||||
|
Description: "The ID of the credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
NameKey: {
|
||||||
|
Description: "The name of the credential. Defaults to the resource name.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
DescriptionKey: {
|
||||||
|
Description: "The description of the credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
credentialStoreIdKey: {
|
||||||
|
Description: "ID of the credential store this credential belongs to.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
ForceNew: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
credentialSshPrivateKeyUsernameKey: {
|
||||||
|
Description: "The username associated with the credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
credentialSshPrivateKeyPrivateKeyKey: {
|
||||||
|
Description: "The private key associated with the credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
credentialSshPrivateKeyPrivateKeyHmacKey: {
|
||||||
|
Description: "The private key hmac.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
credentialSshPrivateKeyPassphraseKey: {
|
||||||
|
Description: "The passphrase of the private key associated with the credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
credentialSshPrivateKeyPassphraseHmacKey: {
|
||||||
|
Description: "The private key passphrase hmac.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFromCredentialSshPrivateKeyResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||||
|
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if attrsVal, ok := raw["attributes"]; ok {
|
||||||
|
attrs := attrsVal.(map[string]interface{})
|
||||||
|
if err := d.Set(credentialSshPrivateKeyUsernameKey, attrs[credentialSshPrivateKeyUsernameKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
statePrivKeyHmac := d.Get(credentialSshPrivateKeyPrivateKeyHmacKey)
|
||||||
|
boundaryPrivKeyHmac := attrs[credentialSshPrivateKeyPrivateKeyHmacKey].(string)
|
||||||
|
if statePrivKeyHmac.(string) != boundaryPrivKeyHmac && fromRead {
|
||||||
|
// PrivateKeyHmac has changed in Boundary, therefore the private key has changed.
|
||||||
|
// Update private key value to force tf to attempt update.
|
||||||
|
if err := d.Set(credentialSshPrivateKeyPrivateKeyKey, "(changed in Boundary)"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialSshPrivateKeyPrivateKeyHmacKey, boundaryPrivKeyHmac); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var statePassphraseHmac, boundaryPassphraseHmac string
|
||||||
|
if v := d.Get(credentialSshPrivateKeyPassphraseHmacKey); v != nil {
|
||||||
|
statePassphraseHmac = v.(string)
|
||||||
|
}
|
||||||
|
if v := attrs[credentialSshPrivateKeyPassphraseHmacKey]; v != nil {
|
||||||
|
boundaryPassphraseHmac = v.(string)
|
||||||
|
}
|
||||||
|
if statePassphraseHmac != boundaryPassphraseHmac && fromRead {
|
||||||
|
// PassphraseHmac has changed in Boundary, therefore the private key passphrase has changed.
|
||||||
|
// Update private key passphrase value to force tf to attempt update.
|
||||||
|
if err := d.Set(credentialSshPrivateKeyPassphraseKey, "(changed in Boundary)"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialSshPrivateKeyPassphraseHmacKey, boundaryPassphraseHmac); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(raw["id"].(string))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialSshPrivateKeyCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
|
||||||
|
var opts []credentials.Option
|
||||||
|
if v, ok := d.GetOk(NameKey); ok {
|
||||||
|
opts = append(opts, credentials.WithName(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||||
|
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(credentialSshPrivateKeyUsernameKey); ok {
|
||||||
|
opts = append(opts, credentials.WithSshPrivateKeyCredentialUsername(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(credentialSshPrivateKeyPrivateKeyKey); ok {
|
||||||
|
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKey(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(credentialSshPrivateKeyPassphraseKey); ok {
|
||||||
|
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKeyPassphrase(v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var credentialStoreId string
|
||||||
|
retrievedStoreId, ok := d.GetOk(credentialStoreIdKey)
|
||||||
|
if ok {
|
||||||
|
credentialStoreId = retrievedStoreId.(string)
|
||||||
|
} else {
|
||||||
|
return diag.Errorf("credential store id is unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
cr, err := client.Create(ctx, credentialSshPrivateKeyCredentialType, credentialStoreId, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error creating credential: %v", err)
|
||||||
|
}
|
||||||
|
if cr == nil {
|
||||||
|
return diag.Errorf("nil credential after create")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFromCredentialSshPrivateKeyResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialSshPrivateKeyRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
cr, err := client.Read(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return diag.Errorf("error reading credential: %v", err)
|
||||||
|
}
|
||||||
|
if cr == nil {
|
||||||
|
return diag.Errorf("credential nil after read")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFromCredentialSshPrivateKeyResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialSshPrivateKeyUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
var opts []credentials.Option
|
||||||
|
if d.HasChange(NameKey) {
|
||||||
|
opts = append(opts, credentials.DefaultName())
|
||||||
|
nameVal, ok := d.GetOk(NameKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithName(nameVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(DescriptionKey) {
|
||||||
|
opts = append(opts, credentials.DefaultDescription())
|
||||||
|
descVal, ok := d.GetOk(DescriptionKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithDescription(descVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(credentialSshPrivateKeyUsernameKey) {
|
||||||
|
usernameVal, ok := d.GetOk(credentialSshPrivateKeyUsernameKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithSshPrivateKeyCredentialUsername(usernameVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(credentialSshPrivateKeyPrivateKeyKey) {
|
||||||
|
privKeyVal, ok := d.GetOk(credentialSshPrivateKeyPrivateKeyKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKey(privKeyVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(credentialSshPrivateKeyPassphraseKey) {
|
||||||
|
passVal, ok := d.GetOk(credentialSshPrivateKeyPassphraseKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithSshPrivateKeyCredentialPrivateKeyPassphrase(passVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts) > 0 {
|
||||||
|
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||||
|
crUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error updating credential: %v", err)
|
||||||
|
}
|
||||||
|
if crUpdate == nil {
|
||||||
|
return diag.Errorf("credential nil after update")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = setFromCredentialSshPrivateKeyResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialSshPrivateKeyDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
_, err := client.Delete(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error deleting credential: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,180 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentials"
|
||||||
|
"github.com/hashicorp/boundary/testing/controller"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||||
|
"golang.org/x/crypto/ssh/testdata"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sshPrivateKeyCredResc = "boundary_credential_ssh_private_key.example"
|
||||||
|
sshPrivateKeyCredName = "Dr Jekyll"
|
||||||
|
sshPrivateKeyCredDesc = "my best description"
|
||||||
|
sshPrivateKeyUpdate = "some magic update string"
|
||||||
|
sshPrivateKeyUsername = "my-user"
|
||||||
|
)
|
||||||
|
|
||||||
|
var staticStore = fmt.Sprintf(`
|
||||||
|
resource "boundary_credential_store_static" "ssh_store" {
|
||||||
|
name = "static store name"
|
||||||
|
description = "static store description"
|
||||||
|
scope_id = boundary_scope.proj1.id
|
||||||
|
depends_on = [boundary_role.proj1_admin]
|
||||||
|
}`)
|
||||||
|
|
||||||
|
func sshPrivateKeyResource(name, description, username, privateKey, passphrase string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "boundary_credential_ssh_private_key" "example" {
|
||||||
|
name = %q
|
||||||
|
description = %q
|
||||||
|
credential_store_id = boundary_credential_store_static.ssh_store.id
|
||||||
|
username = %q
|
||||||
|
private_key = %q
|
||||||
|
private_key_passphrase = %q
|
||||||
|
}`, name, description, username, privateKey, passphrase)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccCredentialSshPrivateKey(t *testing.T) {
|
||||||
|
tc := controller.NewTestController(t, tcConfig...)
|
||||||
|
defer tc.Shutdown()
|
||||||
|
url := tc.ApiAddrs()[0]
|
||||||
|
|
||||||
|
privKey := string(testdata.PEMBytes["rsa"])
|
||||||
|
privKeyUpdate := string(testdata.PEMEncryptedKeys[0].PEMBytes)
|
||||||
|
privKeyUpdatePassphrase := testdata.PEMEncryptedKeys[0].EncryptionKey
|
||||||
|
|
||||||
|
res := sshPrivateKeyResource(
|
||||||
|
sshPrivateKeyCredName,
|
||||||
|
sshPrivateKeyCredDesc,
|
||||||
|
sshPrivateKeyUsername,
|
||||||
|
privKey,
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
||||||
|
resUpdate := sshPrivateKeyResource(
|
||||||
|
sshPrivateKeyCredName+sshPrivateKeyUpdate,
|
||||||
|
sshPrivateKeyCredDesc+sshPrivateKeyUpdate,
|
||||||
|
sshPrivateKeyUsername+sshPrivateKeyUpdate,
|
||||||
|
privKeyUpdate,
|
||||||
|
privKeyUpdatePassphrase,
|
||||||
|
)
|
||||||
|
|
||||||
|
var provider *schema.Provider
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
IsUnitTest: true,
|
||||||
|
ProviderFactories: providerFactories(&provider),
|
||||||
|
CheckDestroy: testAccCheckCredentialSshPrivateKeyResourceDestroy(t, provider),
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
// create
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, staticStore, res),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, NameKey, sshPrivateKeyCredName),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, DescriptionKey, sshPrivateKeyCredDesc),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyUsernameKey, sshPrivateKeyUsername),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPrivateKeyKey, privKey),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPassphraseKey, ""),
|
||||||
|
|
||||||
|
testAccCheckCredentialStoreSshPrivateKeyHmac(provider),
|
||||||
|
testAccCheckCredentialSshPrivateKeyResourceExists(provider, sshPrivateKeyCredResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(sshPrivateKeyCredResc, credentialSshPrivateKeyPrivateKeyKey, credentialSshPrivateKeyPassphraseKey),
|
||||||
|
{
|
||||||
|
// update
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, staticStore, resUpdate),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, NameKey, sshPrivateKeyCredName+sshPrivateKeyUpdate),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, DescriptionKey, sshPrivateKeyCredDesc+sshPrivateKeyUpdate),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyUsernameKey, sshPrivateKeyUsername+sshPrivateKeyUpdate),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPrivateKeyKey, privKeyUpdate),
|
||||||
|
resource.TestCheckResourceAttr(sshPrivateKeyCredResc, credentialSshPrivateKeyPassphraseKey, privKeyUpdatePassphrase),
|
||||||
|
|
||||||
|
testAccCheckCredentialStoreSshPrivateKeyHmac(provider),
|
||||||
|
testAccCheckCredentialSshPrivateKeyResourceExists(provider, sshPrivateKeyCredResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialSshPrivateKeyResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := rs.Primary.ID
|
||||||
|
if id == "" {
|
||||||
|
return fmt.Errorf("no ID is set")
|
||||||
|
}
|
||||||
|
storeId = id
|
||||||
|
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
if _, err := c.Read(context.Background(), id); err != nil {
|
||||||
|
return fmt.Errorf("got an error reading %q: %w", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialSshPrivateKeyResourceDestroy(t *testing.T, testProvider *schema.Provider) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
if testProvider.Meta() == nil {
|
||||||
|
t.Fatal("got nil provider metadata")
|
||||||
|
}
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
|
||||||
|
for _, rs := range s.RootModule().Resources {
|
||||||
|
switch rs.Type {
|
||||||
|
case "boundary_credential_ssh_private_key":
|
||||||
|
id := rs.Primary.ID
|
||||||
|
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
_, err := c.Read(context.Background(), id)
|
||||||
|
if apiErr := api.AsServerError(err); apiErr == nil || apiErr.Response().StatusCode() != http.StatusNotFound {
|
||||||
|
return fmt.Errorf("didn't get a 404 when reading destroyed credential %q: %v", id, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialStoreSshPrivateKeyHmac(testProvider *schema.Provider) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[sshPrivateKeyCredResc]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found: %s", sshPrivateKeyCredResc)
|
||||||
|
}
|
||||||
|
|
||||||
|
computed := rs.Primary.Attributes["private_key_hmac"]
|
||||||
|
if len(computed) != 43 {
|
||||||
|
return fmt.Errorf("computed private key hmac not the expected length of 43 characters, got: %q", computed)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rs.Primary.Attributes["private_key_passphrase"] != "" {
|
||||||
|
// We set a passphrase, validate the computed hmac is expected length
|
||||||
|
computed := rs.Primary.Attributes["private_key_passphrase_hmac"]
|
||||||
|
if len(computed) != 43 {
|
||||||
|
return fmt.Errorf("computed private key passphrase hmac not the expected length of 43 characters, got: %q", computed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,176 @@
|
|||||||
|
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 staticCredentialStoreType = "static"
|
||||||
|
|
||||||
|
func resourceCredentialStoreStatic() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Description: "The static credential store resource allows you to configure a Boundary static credential store.",
|
||||||
|
|
||||||
|
CreateContext: resourceStaticCredentialStoreCreate,
|
||||||
|
ReadContext: resourceStaticCredentialStoreRead,
|
||||||
|
UpdateContext: resourceStaticCredentialStoreUpdate,
|
||||||
|
DeleteContext: resourceStaticCredentialStoreDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
StateContext: schema.ImportStatePassthroughContext,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
IDKey: {
|
||||||
|
Description: "The ID of the static credential store.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
NameKey: {
|
||||||
|
Description: "The static credential store name. Defaults to the resource name.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
DescriptionKey: {
|
||||||
|
Description: "The static credential store description.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
ScopeIdKey: {
|
||||||
|
Description: "The scope for this credential store.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
ForceNew: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFromStaticCredentialStoreResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||||
|
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(ScopeIdKey, raw[ScopeIdKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(raw["id"].(string))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStaticCredentialStoreCreate(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)))
|
||||||
|
}
|
||||||
|
|
||||||
|
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, staticCredentialStoreType, 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 := setFromStaticCredentialStoreResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential store from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStaticCredentialStoreRead(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 := setFromStaticCredentialStoreResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
||||||
|
return diag.Errorf("error generating credential store from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStaticCredentialStoreUpdate(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 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 = setFromStaticCredentialStoreResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential store from response map: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceStaticCredentialStoreDelete(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,139 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentialstores"
|
||||||
|
"github.com/hashicorp/boundary/testing/controller"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
staticCredStoreResc = "boundary_credential_store_static.example"
|
||||||
|
staticCredStoreName = "foo"
|
||||||
|
staticCredStoreDesc = "the foo"
|
||||||
|
staticCredStoreNamespace = "static"
|
||||||
|
staticCredStoreUpdate = "_random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func staticCredStoreResource(name string, description string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "%s"
|
||||||
|
description = "%s"
|
||||||
|
scope_id = boundary_scope.proj1.id
|
||||||
|
depends_on = [boundary_role.proj1_admin]
|
||||||
|
}`, name,
|
||||||
|
description)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccCredentialStoreStatic(t *testing.T) {
|
||||||
|
tc := controller.NewTestController(t, tcConfig...)
|
||||||
|
defer tc.Shutdown()
|
||||||
|
url := tc.ApiAddrs()[0]
|
||||||
|
|
||||||
|
res := staticCredStoreResource(staticCredStoreName,
|
||||||
|
staticCredStoreDesc)
|
||||||
|
|
||||||
|
resUpdate := staticCredStoreResource(staticCredStoreName+staticCredStoreUpdate,
|
||||||
|
staticCredStoreDesc+staticCredStoreUpdate)
|
||||||
|
|
||||||
|
var provider *schema.Provider
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
ProviderFactories: providerFactories(&provider),
|
||||||
|
CheckDestroy: testAccCheckCredentialStoreStaticResourceDestroy(t, provider),
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
// create
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(staticCredStoreResc, NameKey, staticCredStoreName),
|
||||||
|
resource.TestCheckResourceAttr(staticCredStoreResc, DescriptionKey, staticCredStoreDesc),
|
||||||
|
|
||||||
|
testAccCheckCredentialStoreVaultResourceExists(provider, staticCredStoreResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(staticCredStoreResc),
|
||||||
|
{
|
||||||
|
// update
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(staticCredStoreResc, NameKey, staticCredStoreName+staticCredStoreUpdate),
|
||||||
|
resource.TestCheckResourceAttr(staticCredStoreResc, DescriptionKey, staticCredStoreDesc+staticCredStoreUpdate),
|
||||||
|
|
||||||
|
testAccCheckCredentialStoreVaultResourceExists(provider, staticCredStoreResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(staticCredStoreResc),
|
||||||
|
{
|
||||||
|
// Run a plan only update and verify no changes
|
||||||
|
PlanOnly: true,
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
},
|
||||||
|
importStep(staticCredStoreResc),
|
||||||
|
{
|
||||||
|
// update again but apply a preConfig to externally update resource
|
||||||
|
// TODO: Boundary currently causes an error on moving back to a previously
|
||||||
|
// used token, for now verify that a plan only step had changes
|
||||||
|
PreConfig: func() { staticCredentialStoreExternalUpdate(t, provider) },
|
||||||
|
PlanOnly: true,
|
||||||
|
ExpectNonEmptyPlan: true,
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
},
|
||||||
|
importStep(staticCredStoreResc),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func staticCredentialStoreExternalUpdate(t *testing.T, testProvider *schema.Provider) {
|
||||||
|
if storeId == "" {
|
||||||
|
t.Fatal("storeId must be set before testing an external update")
|
||||||
|
}
|
||||||
|
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
c := credentialstores.NewClient(md.client)
|
||||||
|
cr, err := c.Read(context.Background(), storeId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(fmt.Errorf("got an error reading %q: %w", storeId, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// update credential store options
|
||||||
|
var opts []credentialstores.Option
|
||||||
|
opts = append(opts, credentialstores.WithDescription("this is an updated description, my guy"))
|
||||||
|
|
||||||
|
_, err = c.Update(context.Background(), cr.Item.Id, cr.Item.Version, opts...)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(fmt.Errorf("got an error updating %q: %w", cr.Item.Id, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialStoreStaticResourceDestroy(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_static":
|
||||||
|
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 static credential store %q: %v", id, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package provider
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/hashicorp/boundary/api"
|
"github.com/hashicorp/boundary/api"
|
||||||
@@ -123,36 +124,49 @@ func resourceCredentialStoreVault() *schema.Resource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setFromVaultCredentialStoreResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
func setFromVaultCredentialStoreResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) diag.Diagnostics {
|
||||||
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||||
return err
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||||
return err
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
if err := d.Set(ScopeIdKey, raw[ScopeIdKey]); err != nil {
|
if err := d.Set(ScopeIdKey, raw[ScopeIdKey]); err != nil {
|
||||||
return err
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var diags diag.Diagnostics
|
||||||
|
csId := raw["id"]
|
||||||
if attrsVal, ok := raw["attributes"]; ok {
|
if attrsVal, ok := raw["attributes"]; ok {
|
||||||
attrs := attrsVal.(map[string]interface{})
|
attrs := attrsVal.(map[string]interface{})
|
||||||
for _, v := range storeVaultAttrs {
|
for _, v := range storeVaultAttrs {
|
||||||
if err := d.Set(v, attrs[v]); err != nil {
|
if err := d.Set(v, attrs[v]); err != nil {
|
||||||
return err
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stateTokenHmac := d.Get(credentialStoreVaultTokenHmacKey)
|
boundaryTokenHmac, ok := attrs[credentialStoreVaultTokenHmacKey]
|
||||||
boundaryTokenHmac := attrs[credentialStoreVaultTokenHmacKey].(string)
|
tokenStatus := attrs["token_status"]
|
||||||
if stateTokenHmac.(string) != boundaryTokenHmac && fromRead {
|
switch {
|
||||||
// TokenHmac has changed in Boundary, therefore the token has changed.
|
case ok:
|
||||||
// Update token value to force tf to attempt update.
|
boundaryTokenHmacStr := boundaryTokenHmac.(string)
|
||||||
if err := d.Set(credentialStoreVaultTokenKey, "(changed in Boundary)"); err != nil {
|
stateTokenHmac := d.Get(credentialStoreVaultTokenHmacKey)
|
||||||
return err
|
if stateTokenHmac.(string) != boundaryTokenHmacStr && fromRead {
|
||||||
|
// TokenHmac has changed in Boundary, therefore the token has changed.
|
||||||
|
// Update token value to force tf to attempt update.
|
||||||
|
if err := d.Set(credentialStoreVaultTokenKey, "(changed in Boundary)"); err != nil {
|
||||||
|
return diag.FromErr(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if err := d.Set(credentialStoreVaultTokenHmacKey, boundaryTokenHmacStr); err != nil {
|
||||||
if err := d.Set(credentialStoreVaultTokenHmacKey, boundaryTokenHmac); err != nil {
|
return diag.FromErr(err)
|
||||||
return err
|
}
|
||||||
|
|
||||||
|
case tokenStatus == "expired":
|
||||||
|
diags = append(diags, diag.Diagnostic{
|
||||||
|
Severity: diag.Warning,
|
||||||
|
Summary: fmt.Sprintf("Vault token has expired for credential store %q, please update.", csId),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
stateClientKeyHmac := d.Get(credentialStoreVaultClientCertificateKeyHmacKey)
|
stateClientKeyHmac := d.Get(credentialStoreVaultClientCertificateKeyHmacKey)
|
||||||
@@ -164,17 +178,17 @@ func setFromVaultCredentialStoreResponseMap(d *schema.ResourceData, raw map[stri
|
|||||||
// ClientKeyHmac has changed in Boundary, therefore the ClientKey has changed.
|
// ClientKeyHmac has changed in Boundary, therefore the ClientKey has changed.
|
||||||
// Update ClientKey value to force tf to attempt update.
|
// Update ClientKey value to force tf to attempt update.
|
||||||
if err := d.Set(credentialStoreVaultClientCertificateKeyKey, "(changed in Boundary)"); err != nil {
|
if err := d.Set(credentialStoreVaultClientCertificateKeyKey, "(changed in Boundary)"); err != nil {
|
||||||
return err
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := d.Set(credentialStoreVaultClientCertificateKeyHmacKey, boundaryClientKeyHmac); err != nil {
|
if err := d.Set(credentialStoreVaultClientCertificateKeyHmacKey, boundaryClientKeyHmac); err != nil {
|
||||||
return err
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetId(raw["id"].(string))
|
d.SetId(csId.(string))
|
||||||
|
|
||||||
return nil
|
return diags
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceCredentialStoreVaultCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
func resourceCredentialStoreVaultCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
@@ -229,8 +243,8 @@ func resourceCredentialStoreVaultCreate(ctx context.Context, d *schema.ResourceD
|
|||||||
return diag.Errorf("nil credential store after create")
|
return diag.Errorf("nil credential store after create")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setFromVaultCredentialStoreResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
if diagnostics := setFromVaultCredentialStoreResponseMap(d, cr.GetResponse().Map, false); diagnostics != nil {
|
||||||
return diag.Errorf("error generating credential store from response map: %v", err)
|
return diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -252,8 +266,8 @@ func resourceCredentialStoreVaultRead(ctx context.Context, d *schema.ResourceDat
|
|||||||
return diag.Errorf("credential store nil after read")
|
return diag.Errorf("credential store nil after read")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := setFromVaultCredentialStoreResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
if diagnostics := setFromVaultCredentialStoreResponseMap(d, cr.GetResponse().Map, true); diagnostics != nil {
|
||||||
return diag.Errorf("error generating credential store from response map: %v", err)
|
return diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -352,8 +366,8 @@ func resourceCredentialStoreVaultUpdate(ctx context.Context, d *schema.ResourceD
|
|||||||
return diag.Errorf("credential store nil after update")
|
return diag.Errorf("credential store nil after update")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = setFromVaultCredentialStoreResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
if diagnostics := setFromVaultCredentialStoreResponseMap(d, crUpdate.GetResponse().Map, false); diagnostics != nil {
|
||||||
return diag.Errorf("error generating credential store from response map: %v", err)
|
return diagnostics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,237 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentials"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
credentialUsernamePasswordUsernameKey = "username"
|
||||||
|
credentialUsernamePasswordPasswordKey = "password"
|
||||||
|
credentialUsernamePasswordPasswordHmacKey = "password_hmac"
|
||||||
|
credentialUsernamePasswordCredentialType = "username_password"
|
||||||
|
)
|
||||||
|
|
||||||
|
func resourceCredentialUsernamePassword() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Description: "The username/password credential resource allows you to configure a credential using a username and password pair.",
|
||||||
|
|
||||||
|
CreateContext: resourceCredentialUsernamePasswordCreate,
|
||||||
|
ReadContext: resourceCredentialUsernamePasswordRead,
|
||||||
|
UpdateContext: resourceCredentialUsernamePasswordUpdate,
|
||||||
|
DeleteContext: resourceCredentialUsernamePasswordDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
StateContext: schema.ImportStatePassthroughContext,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
IDKey: {
|
||||||
|
Description: "The ID of this username/password credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
NameKey: {
|
||||||
|
Description: "The name of this username/password credential. Defaults to the resource name.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
DescriptionKey: {
|
||||||
|
Description: "The description of this username/password credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
credentialStoreIdKey: {
|
||||||
|
Description: "The credential store in which to save this username/password credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
ForceNew: true,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
credentialUsernamePasswordUsernameKey: {
|
||||||
|
Description: "The username of this username/password credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
credentialUsernamePasswordPasswordKey: {
|
||||||
|
Description: "The password of this username/password credential.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
Sensitive: true,
|
||||||
|
},
|
||||||
|
credentialUsernamePasswordPasswordHmacKey: {
|
||||||
|
Description: "The password hmac.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Computed: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setFromCredentialUsernamePasswordResponseMap(d *schema.ResourceData, raw map[string]interface{}, fromRead bool) error {
|
||||||
|
if err := d.Set(NameKey, raw[NameKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(DescriptionKey, raw[DescriptionKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialStoreIdKey, raw[credentialStoreIdKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if attrsVal, ok := raw["attributes"]; ok {
|
||||||
|
attrs := attrsVal.(map[string]interface{})
|
||||||
|
if err := d.Set(credentialUsernamePasswordUsernameKey, attrs[credentialUsernamePasswordUsernameKey]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
statePasswordHmac := d.Get(credentialUsernamePasswordPasswordHmacKey)
|
||||||
|
boundaryPasswordHmac := attrs[credentialUsernamePasswordPasswordHmacKey].(string)
|
||||||
|
if statePasswordHmac.(string) != boundaryPasswordHmac && fromRead {
|
||||||
|
// PasswordHmac has changed in Boundary, therefore the password has changed.
|
||||||
|
// Update password value to force tf to attempt update.
|
||||||
|
if err := d.Set(credentialUsernamePasswordPasswordKey, "(changed in Boundary)"); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := d.Set(credentialUsernamePasswordPasswordHmacKey, boundaryPasswordHmac); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(raw["id"].(string))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialUsernamePasswordCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
|
||||||
|
var opts []credentials.Option
|
||||||
|
if v, ok := d.GetOk(NameKey); ok {
|
||||||
|
opts = append(opts, credentials.WithName(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(DescriptionKey); ok {
|
||||||
|
opts = append(opts, credentials.WithDescription(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(credentialUsernamePasswordUsernameKey); ok {
|
||||||
|
opts = append(opts, credentials.WithUsernamePasswordCredentialUsername(v.(string)))
|
||||||
|
}
|
||||||
|
if v, ok := d.GetOk(credentialUsernamePasswordPasswordKey); ok {
|
||||||
|
opts = append(opts, credentials.WithUsernamePasswordCredentialPassword(v.(string)))
|
||||||
|
}
|
||||||
|
|
||||||
|
var credentialStoreId string
|
||||||
|
retrievedStoreId, ok := d.GetOk(credentialStoreIdKey)
|
||||||
|
if ok {
|
||||||
|
credentialStoreId = retrievedStoreId.(string)
|
||||||
|
} else {
|
||||||
|
return diag.Errorf("credential store id is unset")
|
||||||
|
}
|
||||||
|
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
cr, err := client.Create(ctx, credentialUsernamePasswordCredentialType, credentialStoreId, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error creating credential: %v", err)
|
||||||
|
}
|
||||||
|
if cr == nil {
|
||||||
|
return diag.Errorf("nil credential after create")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFromCredentialUsernamePasswordResponseMap(d, cr.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialUsernamePasswordRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
cr, err := client.Read(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound {
|
||||||
|
d.SetId("")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return diag.Errorf("error reading credential: %v", err)
|
||||||
|
}
|
||||||
|
if cr == nil {
|
||||||
|
return diag.Errorf("credential nil after read")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := setFromCredentialUsernamePasswordResponseMap(d, cr.GetResponse().Map, true); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialUsernamePasswordUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
var opts []credentials.Option
|
||||||
|
if d.HasChange(NameKey) {
|
||||||
|
opts = append(opts, credentials.DefaultName())
|
||||||
|
nameVal, ok := d.GetOk(NameKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithName(nameVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(DescriptionKey) {
|
||||||
|
opts = append(opts, credentials.DefaultDescription())
|
||||||
|
descVal, ok := d.GetOk(DescriptionKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithDescription(descVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(credentialUsernamePasswordUsernameKey) {
|
||||||
|
usernameVal, ok := d.GetOk(credentialUsernamePasswordUsernameKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithUsernamePasswordCredentialUsername(usernameVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(credentialUsernamePasswordPasswordKey) {
|
||||||
|
passwordVal, ok := d.GetOk(credentialUsernamePasswordPasswordKey)
|
||||||
|
if ok {
|
||||||
|
opts = append(opts, credentials.WithUsernamePasswordCredentialPassword(passwordVal.(string)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(opts) > 0 {
|
||||||
|
opts = append(opts, credentials.WithAutomaticVersioning(true))
|
||||||
|
crUpdate, err := client.Update(ctx, d.Id(), 0, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error updating credential: %v", err)
|
||||||
|
}
|
||||||
|
if crUpdate == nil {
|
||||||
|
return diag.Errorf("credential nil after update")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = setFromCredentialUsernamePasswordResponseMap(d, crUpdate.GetResponse().Map, false); err != nil {
|
||||||
|
return diag.Errorf("error generating credential from response map: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceCredentialUsernamePasswordDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
|
md := meta.(*metaData)
|
||||||
|
client := credentials.NewClient(md.client)
|
||||||
|
|
||||||
|
_, err := client.Delete(ctx, d.Id())
|
||||||
|
if err != nil {
|
||||||
|
return diag.Errorf("error deleting credential: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,199 @@
|
|||||||
|
package provider
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/boundary/api"
|
||||||
|
"github.com/hashicorp/boundary/api/credentials"
|
||||||
|
"github.com/hashicorp/boundary/testing/controller"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
|
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
usernamePasswordCredResc = "boundary_credential_username_password.example"
|
||||||
|
usernamePasswordCredName = "foo"
|
||||||
|
usernamePasswordCredDesc = "the foo"
|
||||||
|
usernamePasswordCredUsername = "default_username"
|
||||||
|
usernamePasswordCredPassword = "default_password"
|
||||||
|
usernamePasswordCredUpdate = "_random"
|
||||||
|
)
|
||||||
|
|
||||||
|
func usernamePasswordCredResource(name, description, username, password string) string {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
resource "boundary_credential_store_static" "example" {
|
||||||
|
name = "static store name"
|
||||||
|
description = "static store description"
|
||||||
|
scope_id = boundary_scope.proj1.id
|
||||||
|
depends_on = [boundary_role.proj1_admin]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "boundary_credential_username_password" "example" {
|
||||||
|
name = "%s"
|
||||||
|
description = "%s"
|
||||||
|
credential_store_id = boundary_credential_store_static.example.id
|
||||||
|
username = "%s"
|
||||||
|
password = "%s"
|
||||||
|
}`, name,
|
||||||
|
description,
|
||||||
|
username,
|
||||||
|
password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAccCredentialUsernamePassword(t *testing.T) {
|
||||||
|
tc := controller.NewTestController(t, tcConfig...)
|
||||||
|
defer tc.Shutdown()
|
||||||
|
url := tc.ApiAddrs()[0]
|
||||||
|
|
||||||
|
res := usernamePasswordCredResource(
|
||||||
|
usernamePasswordCredName,
|
||||||
|
usernamePasswordCredDesc,
|
||||||
|
usernamePasswordCredUsername,
|
||||||
|
usernamePasswordCredPassword,
|
||||||
|
)
|
||||||
|
|
||||||
|
resUpdate := usernamePasswordCredResource(
|
||||||
|
usernamePasswordCredName,
|
||||||
|
usernamePasswordCredDesc,
|
||||||
|
usernamePasswordCredUsername+usernamePasswordCredUpdate,
|
||||||
|
usernamePasswordCredPassword+usernamePasswordCredUpdate,
|
||||||
|
)
|
||||||
|
|
||||||
|
var provider *schema.Provider
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
ProviderFactories: providerFactories(&provider),
|
||||||
|
CheckDestroy: testAccCheckCredentialUsernamePasswordResourceDestroy(t, provider),
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
// create
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, res),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, NameKey, usernamePasswordCredName),
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, DescriptionKey, usernamePasswordCredDesc),
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, credentialUsernamePasswordUsernameKey, usernamePasswordCredUsername),
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, credentialUsernamePasswordPasswordKey, usernamePasswordCredPassword),
|
||||||
|
|
||||||
|
testAccCheckCredentialStoreUsernamePasswordHmac(provider),
|
||||||
|
testAccCheckCredentialUsernamePasswordResourceExists(provider, usernamePasswordCredResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(usernamePasswordCredResc, credentialUsernamePasswordPasswordKey),
|
||||||
|
{
|
||||||
|
// update
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, NameKey, usernamePasswordCredName),
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, DescriptionKey, usernamePasswordCredDesc),
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, credentialUsernamePasswordUsernameKey, usernamePasswordCredUsername+usernamePasswordCredUpdate),
|
||||||
|
resource.TestCheckResourceAttr(usernamePasswordCredResc, credentialUsernamePasswordPasswordKey, usernamePasswordCredPassword+usernamePasswordCredUpdate),
|
||||||
|
|
||||||
|
testAccCheckCredentialStoreUsernamePasswordHmac(provider),
|
||||||
|
testAccCheckCredentialUsernamePasswordResourceExists(provider, usernamePasswordCredResc),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
importStep(usernamePasswordCredResc, credentialUsernamePasswordPasswordKey),
|
||||||
|
{
|
||||||
|
// Run a plan only update and verify no changes
|
||||||
|
PlanOnly: true,
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
},
|
||||||
|
importStep(usernamePasswordCredResc, credentialUsernamePasswordPasswordKey),
|
||||||
|
{
|
||||||
|
// update again but apply a preConfig to externally update resource
|
||||||
|
PreConfig: func() { usernamePasswordCredExternalUpdate(t, provider) },
|
||||||
|
Config: testConfig(url, fooOrg, firstProjectFoo, resUpdate),
|
||||||
|
},
|
||||||
|
importStep(usernamePasswordCredResc, credentialUsernamePasswordPasswordKey),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func usernamePasswordCredExternalUpdate(t *testing.T, testProvider *schema.Provider) {
|
||||||
|
if storeId == "" {
|
||||||
|
t.Fatal("storeId must be set before testing an external update")
|
||||||
|
}
|
||||||
|
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
cr, err := c.Read(context.Background(), storeId)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(fmt.Errorf("got an error reading %q: %w", storeId, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// update credential options
|
||||||
|
var opts []credentials.Option
|
||||||
|
opts = append(opts, credentials.WithDescription("this is an updated description, my guy"))
|
||||||
|
|
||||||
|
_, err = c.Update(context.Background(), cr.Item.Id, cr.Item.Version, opts...)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(fmt.Errorf("got an error updating %q: %w", cr.Item.Id, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialUsernamePasswordResourceExists(testProvider *schema.Provider, name string) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found: %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
id := rs.Primary.ID
|
||||||
|
if id == "" {
|
||||||
|
return fmt.Errorf("no ID is set")
|
||||||
|
}
|
||||||
|
storeId = id
|
||||||
|
|
||||||
|
md := testProvider.Meta().(*metaData)
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
if _, err := c.Read(context.Background(), id); err != nil {
|
||||||
|
return fmt.Errorf("got an error reading %q: %w", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialUsernamePasswordResourceDestroy(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_username_password":
|
||||||
|
id := rs.Primary.ID
|
||||||
|
|
||||||
|
c := credentials.NewClient(md.client)
|
||||||
|
_, err := c.Read(context.Background(), id)
|
||||||
|
if apiErr := api.AsServerError(err); apiErr == nil || apiErr.Response().StatusCode() != http.StatusNotFound {
|
||||||
|
return fmt.Errorf("didn't get a 404 when reading destroyed username password credential %q: %v", id, err)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckCredentialStoreUsernamePasswordHmac(testProvider *schema.Provider) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[usernamePasswordCredResc]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found: %s", usernamePasswordCredResc)
|
||||||
|
}
|
||||||
|
|
||||||
|
computed := rs.Primary.Attributes["password_hmac"]
|
||||||
|
if len(computed) != 43 {
|
||||||
|
return fmt.Errorf("Computed password hmac not the expected length of 43 characters. hmac: %q", computed)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,8 +16,8 @@ const (
|
|||||||
|
|
||||||
func resourceHostCatalog() *schema.Resource {
|
func resourceHostCatalog() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
DeprecationMessage: "Deprecated: use `resource_host_catalog_static` instead.",
|
DeprecationMessage: "Deprecated: use `boundary_host_catalog_static` instead.",
|
||||||
Description: "Deprecated: use `resource_host_catalog_static` instead.",
|
Description: "Deprecated: use `boundary_host_catalog_static` instead.",
|
||||||
|
|
||||||
CreateContext: resourceHostCatalogStaticCreate(true),
|
CreateContext: resourceHostCatalogStaticCreate(true),
|
||||||
ReadContext: resourceHostCatalogStaticRead(true),
|
ReadContext: resourceHostCatalogStaticRead(true),
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ const (
|
|||||||
|
|
||||||
func resourceHostSet() *schema.Resource {
|
func resourceHostSet() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
DeprecationMessage: "Deprecated: use `resource_host_set_static` instead.",
|
DeprecationMessage: "Deprecated: use `boundary_host_set_static` instead.",
|
||||||
Description: "Deprecated: use `resource_host_set_static` instead.",
|
Description: "Deprecated: use `boundary_host_set_static` instead.",
|
||||||
|
|
||||||
CreateContext: resourceHostSetStaticCreate,
|
CreateContext: resourceHostSetStaticCreate,
|
||||||
ReadContext: resourceHostSetStaticRead,
|
ReadContext: resourceHostSetStaticRead,
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ const (
|
|||||||
|
|
||||||
func resourceHost() *schema.Resource {
|
func resourceHost() *schema.Resource {
|
||||||
return &schema.Resource{
|
return &schema.Resource{
|
||||||
DeprecationMessage: "Deprecated: use `resource_host_static` instead.",
|
DeprecationMessage: "Deprecated: use `boundary_host_static` instead.",
|
||||||
Description: "Deprecated: use `resource_host_static` instead.",
|
Description: "Deprecated: use `boundary_host_static` instead.",
|
||||||
|
|
||||||
CreateContext: resourceHostStaticCreate,
|
CreateContext: resourceHostStaticCreate,
|
||||||
ReadContext: resourceHostStaticRead,
|
ReadContext: resourceHostStaticRead,
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ const (
|
|||||||
roleGrantScopeIdKey = "grant_scope_id"
|
roleGrantScopeIdKey = "grant_scope_id"
|
||||||
rolePrincipalIdsKey = "principal_ids"
|
rolePrincipalIdsKey = "principal_ids"
|
||||||
roleGrantStringsKey = "grant_strings"
|
roleGrantStringsKey = "grant_strings"
|
||||||
roleDefaultRoleKey = "default_role"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceRole() *schema.Resource {
|
func resourceRole() *schema.Resource {
|
||||||
@@ -68,11 +67,6 @@ func resourceRole() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
Computed: true,
|
Computed: true,
|
||||||
},
|
},
|
||||||
roleDefaultRoleKey: {
|
|
||||||
Type: schema.TypeBool,
|
|
||||||
Optional: true,
|
|
||||||
Description: "Indicates that the role containing this value is the default role (that is, has the id 'r_default'), which triggers some specialized behavior to allow it to be imported and managed.",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,11 +95,6 @@ func setFromRoleResponseMap(d *schema.ResourceData, raw map[string]interface{})
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
func resourceRoleCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
if d.Get(roleDefaultRoleKey).(bool) {
|
|
||||||
d.SetId("r_default")
|
|
||||||
return resourceRoleRead(ctx, d, meta)
|
|
||||||
}
|
|
||||||
|
|
||||||
md := meta.(*metaData)
|
md := meta.(*metaData)
|
||||||
|
|
||||||
var scopeId string
|
var scopeId string
|
||||||
@@ -323,10 +312,6 @@ func resourceRoleUpdate(ctx context.Context, d *schema.ResourceData, meta interf
|
|||||||
}
|
}
|
||||||
|
|
||||||
func resourceRoleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
func resourceRoleDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
|
||||||
if d.Get(roleDefaultRoleKey).(bool) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
md := meta.(*metaData)
|
md := meta.(*metaData)
|
||||||
rc := roles.NewClient(md.client)
|
rc := roles.NewClient(md.client)
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
targetHostSourceIdsKey = "host_source_ids"
|
targetHostSourceIdsKey = "host_source_ids"
|
||||||
targetApplicationCredentialSourceIdsKey = "application_credential_source_ids"
|
targetBrokeredCredentialSourceIdsKey = "brokered_credential_source_ids"
|
||||||
|
targetInjectedAppCredentialSourceIdsKey = "injected_application_credential_source_ids"
|
||||||
targetDefaultPortKey = "default_port"
|
targetDefaultPortKey = "default_port"
|
||||||
targetSessionMaxSecondsKey = "session_max_seconds"
|
targetSessionMaxSecondsKey = "session_max_seconds"
|
||||||
targetSessionConnectionLimitKey = "session_connection_limit"
|
targetSessionConnectionLimitKey = "session_connection_limit"
|
||||||
targetWorkerFilterKey = "worker_filter"
|
targetWorkerFilterKey = "worker_filter"
|
||||||
|
|
||||||
targetTypeTcp = "tcp"
|
targetTypeTcp = "tcp"
|
||||||
|
targetTypeSsh = "ssh"
|
||||||
)
|
)
|
||||||
|
|
||||||
func resourceTarget() *schema.Resource {
|
func resourceTarget() *schema.Resource {
|
||||||
@@ -73,8 +75,14 @@ func resourceTarget() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
},
|
},
|
||||||
targetApplicationCredentialSourceIdsKey: {
|
targetBrokeredCredentialSourceIdsKey: {
|
||||||
Description: "A list of application credential source ID's.",
|
Description: "A list of brokered credential source ID's.",
|
||||||
|
Type: schema.TypeSet,
|
||||||
|
Optional: true,
|
||||||
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
|
},
|
||||||
|
targetInjectedAppCredentialSourceIdsKey: {
|
||||||
|
Description: "A list of injected application credential source ID's.",
|
||||||
Type: schema.TypeSet,
|
Type: schema.TypeSet,
|
||||||
Optional: true,
|
Optional: true,
|
||||||
Elem: &schema.Schema{Type: schema.TypeString},
|
Elem: &schema.Schema{Type: schema.TypeString},
|
||||||
@@ -114,7 +122,10 @@ func setFromTargetResponseMap(d *schema.ResourceData, raw map[string]interface{}
|
|||||||
if err := d.Set(targetHostSourceIdsKey, raw["host_source_ids"]); err != nil {
|
if err := d.Set(targetHostSourceIdsKey, raw["host_source_ids"]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := d.Set(targetApplicationCredentialSourceIdsKey, raw["application_credential_source_ids"]); err != nil {
|
if err := d.Set(targetBrokeredCredentialSourceIdsKey, raw["brokered_credential_source_ids"]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := d.Set(targetInjectedAppCredentialSourceIdsKey, raw["injected_application_credential_source_ids"]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := d.Set(targetSessionMaxSecondsKey, raw["session_max_seconds"]); err != nil {
|
if err := d.Set(targetSessionMaxSecondsKey, raw["session_max_seconds"]); err != nil {
|
||||||
@@ -128,7 +139,7 @@ func setFromTargetResponseMap(d *schema.ResourceData, raw map[string]interface{}
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch raw["type"].(string) {
|
switch raw["type"].(string) {
|
||||||
case targetTypeTcp:
|
case targetTypeTcp, targetTypeSsh:
|
||||||
if attrsVal, ok := raw["attributes"]; ok {
|
if attrsVal, ok := raw["attributes"]; ok {
|
||||||
attrs := attrsVal.(map[string]interface{})
|
attrs := attrsVal.(map[string]interface{})
|
||||||
if defPort, ok := attrs["default_port"].(json.Number); ok {
|
if defPort, ok := attrs["default_port"].(json.Number); ok {
|
||||||
@@ -161,7 +172,7 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
return diag.Errorf("no type provided")
|
return diag.Errorf("no type provided")
|
||||||
}
|
}
|
||||||
switch typeStr {
|
switch typeStr {
|
||||||
case targetTypeTcp:
|
case targetTypeTcp, targetTypeSsh:
|
||||||
default:
|
default:
|
||||||
return diag.Errorf("invalid type provided")
|
return diag.Errorf("invalid type provided")
|
||||||
}
|
}
|
||||||
@@ -182,10 +193,15 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
defaultPortVal, ok := d.GetOk(targetDefaultPortKey)
|
defaultPortVal, ok := d.GetOk(targetDefaultPortKey)
|
||||||
if ok {
|
if ok {
|
||||||
defaultPortInt := defaultPortVal.(int)
|
defaultPortInt := defaultPortVal.(int)
|
||||||
if defaultPortInt < 0 {
|
if defaultPortInt < 0 || defaultPortInt > 65535 {
|
||||||
return diag.Errorf(`"default_port" cannot be less than zero`)
|
return diag.Errorf(`"default_port" must be a valid tcp port`)
|
||||||
|
}
|
||||||
|
switch typeStr {
|
||||||
|
case targetTypeTcp:
|
||||||
|
opts = append(opts, targets.WithTcpTargetDefaultPort(uint32(defaultPortInt)))
|
||||||
|
case targetTypeSsh:
|
||||||
|
opts = append(opts, targets.WithSshTargetDefaultPort(uint32(defaultPortInt)))
|
||||||
}
|
}
|
||||||
opts = append(opts, targets.WithTcpTargetDefaultPort(uint32(defaultPortInt)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sessionMaxSecondsVal, ok := d.GetOk(targetSessionMaxSecondsKey)
|
sessionMaxSecondsVal, ok := d.GetOk(targetSessionMaxSecondsKey)
|
||||||
@@ -215,12 +231,21 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var credentialSourceIds []string
|
var brokeredCreds []string
|
||||||
if credentialSourceIdsVal, ok := d.GetOk(targetApplicationCredentialSourceIdsKey); ok {
|
if credentialSourceIdsVal, ok := d.GetOk(targetBrokeredCredentialSourceIdsKey); ok {
|
||||||
list := credentialSourceIdsVal.(*schema.Set).List()
|
list := credentialSourceIdsVal.(*schema.Set).List()
|
||||||
credentialSourceIds = make([]string, 0, len(list))
|
brokeredCreds = make([]string, 0, len(list))
|
||||||
for _, i := range list {
|
for _, i := range list {
|
||||||
credentialSourceIds = append(credentialSourceIds, i.(string))
|
brokeredCreds = append(brokeredCreds, i.(string))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var injectedCreds []string
|
||||||
|
if credentialSourceIdsVal, ok := d.GetOk(targetInjectedAppCredentialSourceIdsKey); ok {
|
||||||
|
list := credentialSourceIdsVal.(*schema.Set).List()
|
||||||
|
injectedCreds = make([]string, 0, len(list))
|
||||||
|
for _, i := range list {
|
||||||
|
injectedCreds = append(injectedCreds, i.(string))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,8 +276,15 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
version = tur.Item.Version
|
version = tur.Item.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
if credentialSourceIds != nil {
|
var credOpts []targets.Option
|
||||||
tur, err := tc.SetCredentialSources(ctx, tcr.Item.Id, version, targets.WithApplicationCredentialSourceIds(credentialSourceIds))
|
if brokeredCreds != nil {
|
||||||
|
credOpts = append(credOpts, targets.WithBrokeredCredentialSourceIds(brokeredCreds))
|
||||||
|
}
|
||||||
|
if injectedCreds != nil {
|
||||||
|
credOpts = append(credOpts, targets.WithInjectedApplicationCredentialSourceIds(injectedCreds))
|
||||||
|
}
|
||||||
|
if len(credOpts) > 0 {
|
||||||
|
tur, err := tc.SetCredentialSources(ctx, tcr.Item.Id, version, credOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diag.Errorf("error setting credential sources on target: %v", err)
|
return diag.Errorf("error setting credential sources on target: %v", err)
|
||||||
}
|
}
|
||||||
@@ -295,6 +327,16 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
|
|
||||||
var opts []targets.Option
|
var opts []targets.Option
|
||||||
|
|
||||||
|
var typeStr string
|
||||||
|
if typeVal, ok := d.GetOk(TypeKey); ok {
|
||||||
|
typeStr = typeVal.(string)
|
||||||
|
}
|
||||||
|
switch typeStr {
|
||||||
|
case targetTypeTcp, targetTypeSsh:
|
||||||
|
default:
|
||||||
|
return diag.Errorf("invalid type provided")
|
||||||
|
}
|
||||||
|
|
||||||
var name *string
|
var name *string
|
||||||
if d.HasChange(NameKey) {
|
if d.HasChange(NameKey) {
|
||||||
opts = append(opts, targets.DefaultName())
|
opts = append(opts, targets.DefaultName())
|
||||||
@@ -319,15 +361,30 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
|
|
||||||
var defaultPort *int
|
var defaultPort *int
|
||||||
if d.HasChange(targetDefaultPortKey) {
|
if d.HasChange(targetDefaultPortKey) {
|
||||||
opts = append(opts, targets.DefaultTcpTargetDefaultPort())
|
switch typeStr {
|
||||||
defaultPortVal, ok := d.GetOk(targetDefaultPortKey)
|
case targetTypeTcp:
|
||||||
if ok {
|
opts = append(opts, targets.DefaultTcpTargetDefaultPort())
|
||||||
defaultPortInt := defaultPortVal.(int)
|
defaultPortVal, ok := d.GetOk(targetDefaultPortKey)
|
||||||
if defaultPortInt < 0 {
|
if ok {
|
||||||
return diag.Errorf(`"default_port" cannot be less than zero`)
|
defaultPortInt := defaultPortVal.(int)
|
||||||
|
if defaultPortInt < 0 || defaultPortInt > 65535 {
|
||||||
|
return diag.Errorf(`"default_port" must be a valid tcp port`)
|
||||||
|
}
|
||||||
|
defaultPort = &defaultPortInt
|
||||||
|
opts = append(opts, targets.WithTcpTargetDefaultPort(uint32(defaultPortInt)))
|
||||||
|
}
|
||||||
|
|
||||||
|
case targetTypeSsh:
|
||||||
|
opts = append(opts, targets.DefaultSshTargetDefaultPort())
|
||||||
|
defaultPortVal, ok := d.GetOk(targetDefaultPortKey)
|
||||||
|
if ok {
|
||||||
|
defaultPortInt := defaultPortVal.(int)
|
||||||
|
if defaultPortInt < 0 || defaultPortInt > 65535 {
|
||||||
|
return diag.Errorf(`"default_port" must be a valid tcp port`)
|
||||||
|
}
|
||||||
|
defaultPort = &defaultPortInt
|
||||||
|
opts = append(opts, targets.WithSshTargetDefaultPort(uint32(defaultPortInt)))
|
||||||
}
|
}
|
||||||
defaultPort = &defaultPortInt
|
|
||||||
opts = append(opts, targets.WithTcpTargetDefaultPort(uint32(defaultPortInt)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -428,31 +485,46 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The above calls may not actually happen, so we use d.Id() and automatic
|
// if any of the credential types are changed, then all credential ids must be gathered
|
||||||
// versioning here
|
// because the SetCredentialSources function will remove ids that are not present.
|
||||||
if d.HasChange(targetApplicationCredentialSourceIdsKey) {
|
if d.HasChange(targetBrokeredCredentialSourceIdsKey) || d.HasChange(targetInjectedAppCredentialSourceIdsKey) {
|
||||||
var credentialSourceIds []string
|
credOpts := []targets.Option{
|
||||||
if credentialSourceIdsVal, ok := d.GetOk(targetApplicationCredentialSourceIdsKey); ok {
|
targets.WithAutomaticVersioning(true),
|
||||||
|
}
|
||||||
|
|
||||||
|
if credentialSourceIdsVal, ok := d.GetOk(targetBrokeredCredentialSourceIdsKey); ok {
|
||||||
|
var credentialSourceIds []string
|
||||||
credSourceIds := credentialSourceIdsVal.(*schema.Set).List()
|
credSourceIds := credentialSourceIdsVal.(*schema.Set).List()
|
||||||
for _, credSourceId := range credSourceIds {
|
for _, credSourceId := range credSourceIds {
|
||||||
credentialSourceIds = append(credentialSourceIds, credSourceId.(string))
|
credentialSourceIds = append(credentialSourceIds, credSourceId.(string))
|
||||||
}
|
}
|
||||||
|
credOpts = append(credOpts, targets.WithBrokeredCredentialSourceIds(credentialSourceIds))
|
||||||
}
|
}
|
||||||
|
|
||||||
opts := []targets.Option{
|
if credentialSourceIdsVal, ok := d.GetOk(targetInjectedAppCredentialSourceIdsKey); ok {
|
||||||
targets.WithAutomaticVersioning(true),
|
var credentialSourceIds []string
|
||||||
targets.DefaultApplicationCredentialSourceIds(),
|
credSourceIds := credentialSourceIdsVal.(*schema.Set).List()
|
||||||
}
|
for _, credSourceId := range credSourceIds {
|
||||||
if len(credentialSourceIds) > 0 {
|
credentialSourceIds = append(credentialSourceIds, credSourceId.(string))
|
||||||
opts = append(opts, targets.WithApplicationCredentialSourceIds(credentialSourceIds))
|
}
|
||||||
|
credOpts = append(credOpts, targets.WithInjectedApplicationCredentialSourceIds(credentialSourceIds))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := tc.SetCredentialSources(ctx, d.Id(), 0, opts...)
|
result, err := tc.SetCredentialSources(ctx, d.Id(), 0, credOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diag.Errorf("error updating credential sources in target: %v", err)
|
return diag.Errorf("error updating credential sources in target: %v", err)
|
||||||
}
|
}
|
||||||
if err := d.Set(targetApplicationCredentialSourceIdsKey, credentialSourceIds); err != nil {
|
|
||||||
return diag.FromErr(err)
|
if d.HasChange(targetBrokeredCredentialSourceIdsKey) {
|
||||||
|
if err := d.Set(targetBrokeredCredentialSourceIdsKey, result.Item.BrokeredCredentialSourceIds); err != nil {
|
||||||
|
return diag.FromErr(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.HasChange(targetInjectedAppCredentialSourceIdsKey) {
|
||||||
|
if err := d.Set(targetInjectedAppCredentialSourceIdsKey, result.Item.InjectedApplicationCredentialSourceIds); err != nil {
|
||||||
|
return diag.FromErr(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ resource "boundary_target" "foo" {
|
|||||||
host_source_ids = [
|
host_source_ids = [
|
||||||
boundary_host_set.foo.id
|
boundary_host_set.foo.id
|
||||||
]
|
]
|
||||||
application_credential_source_ids = [
|
brokered_credential_source_ids = [
|
||||||
boundary_credential_library_vault.foo.id
|
boundary_credential_library_vault.foo.id
|
||||||
]
|
]
|
||||||
default_port = 22
|
default_port = 22
|
||||||
@@ -108,7 +108,7 @@ resource "boundary_target" "foo" {
|
|||||||
host_source_ids = [
|
host_source_ids = [
|
||||||
boundary_host_set.bar.id
|
boundary_host_set.bar.id
|
||||||
]
|
]
|
||||||
application_credential_source_ids = [
|
brokered_credential_source_ids = [
|
||||||
boundary_credential_library_vault.bar.id
|
boundary_credential_library_vault.bar.id
|
||||||
]
|
]
|
||||||
default_port = 80
|
default_port = 80
|
||||||
@@ -166,7 +166,7 @@ func TestAccTarget(t *testing.T) {
|
|||||||
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "6"),
|
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "6"),
|
||||||
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "foo"`),
|
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "foo"`),
|
||||||
testAccCheckTargetResourceHostSource(provider, "boundary_target.foo", []string{"boundary_host_set.foo"}),
|
testAccCheckTargetResourceHostSource(provider, "boundary_target.foo", []string{"boundary_host_set.foo"}),
|
||||||
testAccCheckTargetResourceAppCredSources(provider, "boundary_target.foo", []string{"boundary_credential_library_vault.foo"}),
|
testAccCheckTargetResourceBrokeredCredSources(provider, "boundary_target.foo", []string{"boundary_credential_library_vault.foo"}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
importStep("boundary_target.foo"),
|
importStep("boundary_target.foo"),
|
||||||
@@ -181,7 +181,7 @@ func TestAccTarget(t *testing.T) {
|
|||||||
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "7"),
|
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "7"),
|
||||||
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "bar"`),
|
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "bar"`),
|
||||||
testAccCheckTargetResourceHostSource(provider, "boundary_target.foo", []string{"boundary_host_set.bar"}),
|
testAccCheckTargetResourceHostSource(provider, "boundary_target.foo", []string{"boundary_host_set.bar"}),
|
||||||
testAccCheckTargetResourceAppCredSources(provider, "boundary_target.foo", []string{"boundary_credential_library_vault.bar"}),
|
testAccCheckTargetResourceBrokeredCredSources(provider, "boundary_target.foo", []string{"boundary_credential_library_vault.bar"}),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
importStep("boundary_target.foo"),
|
importStep("boundary_target.foo"),
|
||||||
@@ -196,7 +196,7 @@ func TestAccTarget(t *testing.T) {
|
|||||||
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "7"),
|
resource.TestCheckResourceAttr("boundary_target.foo", targetSessionConnectionLimitKey, "7"),
|
||||||
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "bar"`),
|
resource.TestCheckResourceAttr("boundary_target.foo", targetWorkerFilterKey, `type == "bar"`),
|
||||||
testAccCheckTargetResourceHostSource(provider, "boundary_target.foo", nil),
|
testAccCheckTargetResourceHostSource(provider, "boundary_target.foo", nil),
|
||||||
testAccCheckTargetResourceAppCredSources(provider, "boundary_target.foo", nil),
|
testAccCheckTargetResourceBrokeredCredSources(provider, "boundary_target.foo", nil),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
importStep("boundary_target.foo"),
|
importStep("boundary_target.foo"),
|
||||||
@@ -261,7 +261,7 @@ func testAccCheckTargetResourceHostSource(testProvider *schema.Provider, name st
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testAccCheckTargetResourceAppCredSources(testProvider *schema.Provider, name string, credSources []string) resource.TestCheckFunc {
|
func testAccCheckTargetResourceBrokeredCredSources(testProvider *schema.Provider, name string, credSources []string) resource.TestCheckFunc {
|
||||||
return func(s *terraform.State) error {
|
return func(s *terraform.State) error {
|
||||||
rs, ok := s.RootModule().Resources[name]
|
rs, ok := s.RootModule().Resources[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -298,11 +298,11 @@ func testAccCheckTargetResourceAppCredSources(testProvider *schema.Provider, nam
|
|||||||
return fmt.Errorf("got an error when reading target %q: %w", id, err)
|
return fmt.Errorf("got an error when reading target %q: %w", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(t.Item.ApplicationCredentialSourceIds) != len(credSourceIDs) {
|
if len(t.Item.BrokeredCredentialSourceIds) != len(credSourceIDs) {
|
||||||
return fmt.Errorf("tf state and boundary have different number of application credential sources")
|
return fmt.Errorf("tf state and boundary have different number of brokered credential sources")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, stateCredSourceId := range t.Item.ApplicationCredentialSourceIds {
|
for _, stateCredSourceId := range t.Item.BrokeredCredentialSourceIds {
|
||||||
ok := false
|
ok := false
|
||||||
for _, gotCredSourceID := range credSourceIDs {
|
for _, gotCredSourceID := range credSourceIDs {
|
||||||
if gotCredSourceID == stateCredSourceId {
|
if gotCredSourceID == stateCredSourceId {
|
||||||
@@ -310,7 +310,7 @@ func testAccCheckTargetResourceAppCredSources(testProvider *schema.Provider, nam
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("application credential source id in state not set in boundary: %s", stateCredSourceId)
|
return fmt.Errorf("brokered credential source id in state not set in boundary: %s", stateCredSourceId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/darwin/amd64
|
//go:embed assets/darwin/amd64
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/darwin/arm64
|
//go:embed assets/darwin/arm64
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/freebsd/386
|
//go:embed assets/freebsd/386
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/freebsd/amd64
|
//go:embed assets/freebsd/amd64
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/freebsd/arm
|
//go:embed assets/freebsd/arm
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/linux/386
|
//go:embed assets/linux/386
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/linux/amd64
|
//go:embed assets/linux/amd64
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/linux/arm
|
//go:embed assets/linux/arm
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/linux/arm64
|
//go:embed assets/linux/arm64
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/windows/386
|
//go:embed assets/windows/386
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -5,5 +5,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// content is our static kms plugin content.
|
// content is our static kms plugin content.
|
||||||
|
//
|
||||||
//go:embed assets/windows/amd64
|
//go:embed assets/windows/amd64
|
||||||
var content embed.FS
|
var content embed.FS
|
||||||
@@ -4,7 +4,7 @@ go 1.17
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0
|
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.0
|
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0/go.mod h1:bmYifnHykiAB5yR+
|
|||||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 h1:hKWzjzqfUi1HtpBEJ9tLKlRya1u6kRQGZAW9OFR+ia8=
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 h1:hKWzjzqfUi1HtpBEJ9tLKlRya1u6kRQGZAW9OFR+ia8=
|
||||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0/go.mod h1:H+TfVXu/Eyi6Ccs4EoT8pa3gR5lRh12sw4AOq6XkXCg=
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0/go.mod h1:H+TfVXu/Eyi6Ccs4EoT8pa3gR5lRh12sw4AOq6XkXCg=
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2 v2.0.0/go.mod h1:YdrJE0Yqex9DoLBiS0rcfXOQdZKL9j9QJmb+B6rob1g=
|
github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2 v2.0.0/go.mod h1:YdrJE0Yqex9DoLBiS0rcfXOQdZKL9j9QJmb+B6rob1g=
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.0 h1:g8i04iwNWBbbRPNApOVBWKFDO1De6AflcKkp9C3BA2k=
|
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.1 h1:6joKpqCFveaNMEwC3qna67usws6DjdxqfCuQEHSM0aM=
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.0/go.mod h1:sDmsWR/W2LqwU217o32RzdHMb/FywGLF72PVIhpZ3hE=
|
github.com/hashicorp/go-kms-wrapping/wrappers/azurekeyvault/v2 v2.0.1/go.mod h1:sDmsWR/W2LqwU217o32RzdHMb/FywGLF72PVIhpZ3hE=
|
||||||
github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
|
github.com/hashicorp/go-plugin v1.4.3 h1:DXmvivbWD5qdiBts9TpBC7BYL1Aia5sxbRgQB+v6UZM=
|
||||||
github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
github.com/hashicorp/go-plugin v1.4.3/go.mod h1:5fGEH17QVwTTcR0zV7yhDPLLmFX9YSZ38b18Udy6vYQ=
|
||||||
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ module github.com/hashicorp/boundary/plugins/kms/mains/transit
|
|||||||
go 1.17
|
go 1.17
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0
|
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.0
|
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@@ -12,51 +12,51 @@ require (
|
|||||||
github.com/armon/go-radix v1.0.0 // indirect
|
github.com/armon/go-radix v1.0.0 // indirect
|
||||||
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
github.com/cenkalti/backoff/v3 v3.0.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fatih/color v1.7.0 // indirect
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.2 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-hclog v1.1.0 // indirect
|
github.com/hashicorp/go-hclog v1.2.1 // indirect
|
||||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 // indirect
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.5 // indirect
|
||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
github.com/hashicorp/go-plugin v1.4.3 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.6 // indirect
|
github.com/hashicorp/go-retryablehttp v0.6.6 // indirect
|
||||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect
|
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 // indirect
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 // indirect
|
||||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 // indirect
|
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect
|
||||||
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
github.com/hashicorp/go-sockaddr v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||||
github.com/hashicorp/go-version v1.2.0 // indirect
|
github.com/hashicorp/go-version v1.2.0 // indirect
|
||||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/hashicorp/vault/api v1.4.1 // indirect
|
github.com/hashicorp/vault/api v1.7.2 // indirect
|
||||||
github.com/hashicorp/vault/sdk v0.4.1 // indirect
|
github.com/hashicorp/vault/sdk v0.5.1 // indirect
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect
|
||||||
github.com/mattn/go-colorable v0.1.6 // indirect
|
github.com/mattn/go-colorable v0.1.12 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||||
github.com/mitchellh/copystructure v1.0.0 // indirect
|
github.com/mitchellh/copystructure v1.0.0 // indirect
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
github.com/mitchellh/go-testing-interface v1.0.0 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.4.2 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
github.com/mitchellh/reflectwalk v1.0.0 // indirect
|
||||||
github.com/oklog/run v1.0.0 // indirect
|
github.com/oklog/run v1.0.0 // indirect
|
||||||
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
github.com/pierrec/lz4 v2.5.2+incompatible // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
github.com/rogpeppe/go-internal v1.8.1 // indirect
|
||||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||||
github.com/stretchr/testify v1.7.0 // indirect
|
github.com/stretchr/testify v1.7.2 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
|
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000 // indirect
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a // indirect
|
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
|
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20220208230804-65c12eb4c068 // indirect
|
google.golang.org/genproto v0.0.0-20220208230804-65c12eb4c068 // indirect
|
||||||
google.golang.org/grpc v1.44.0 // indirect
|
google.golang.org/grpc v1.44.0 // indirect
|
||||||
google.golang.org/protobuf v1.27.1 // indirect
|
google.golang.org/protobuf v1.27.1 // indirect
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
@@ -40,8 +40,9 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m
|
|||||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
github.com/evanphx/json-patch/v5 v5.5.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||||
|
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
|
||||||
@@ -99,19 +100,20 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S
|
|||||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||||
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||||
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||||
github.com/hashicorp/go-hclog v1.1.0 h1:QsGcniKx5/LuX2eYoeL+Np3UKYPNaN7YKpTh29h8rbw=
|
|
||||||
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
github.com/hashicorp/go-hclog v1.1.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||||
|
github.com/hashicorp/go-hclog v1.2.1 h1:YQsLlGDJgwhXFpucSPyVbCBviQtjlHv3jLTlp8YmtEw=
|
||||||
|
github.com/hashicorp/go-hclog v1.2.1/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc=
|
||||||
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
|
github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g=
|
||||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0 h1:8qUXiUcayCr1RxMzS/D0DK1TPFTlpP8z3cWSR3BUf8E=
|
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2 h1:it114Kjpk79JVh6AfxFMP5oi1gb+RPzcSLiG3zF/J0w=
|
||||||
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.0/go.mod h1:bmYifnHykiAB5yR+FK9fNjvE0GzE1Ev2F4eMTVourcA=
|
github.com/hashicorp/go-kms-wrapping/plugin/v2 v2.0.2/go.mod h1:b9mq0bG5xJ10ZcTEQJLZ22O9y71hIt2MGTLqROA/SAM=
|
||||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0 h1:hKWzjzqfUi1HtpBEJ9tLKlRya1u6kRQGZAW9OFR+ia8=
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.4/go.mod h1:sDQAfwJGv25uGPZA04x87ERglCG6avnRcBT9wYoMII8=
|
||||||
github.com/hashicorp/go-kms-wrapping/v2 v2.0.0/go.mod h1:H+TfVXu/Eyi6Ccs4EoT8pa3gR5lRh12sw4AOq6XkXCg=
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.5 h1:rOFDv+3k05mnW0oaDLffhVUwg03Csn0mvfO98Wdd2bE=
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/aead/v2 v2.0.0/go.mod h1:YdrJE0Yqex9DoLBiS0rcfXOQdZKL9j9QJmb+B6rob1g=
|
github.com/hashicorp/go-kms-wrapping/v2 v2.0.5/go.mod h1:sDQAfwJGv25uGPZA04x87ERglCG6avnRcBT9wYoMII8=
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.0 h1:GCS3ZzGZb9u2Jcg0ILkw2zdGvkNPkpsMmozP/dnM6Z0=
|
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.1 h1:72zlIBTJd2pvYmINqotpvcI4ZXLxhRq2cVPTuqv0xqY=
|
||||||
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.0/go.mod h1:7nyMrL0t9U76zy8ZaNlWKoOYci6cZRvbLFOlhDK9QyQ=
|
github.com/hashicorp/go-kms-wrapping/wrappers/transit/v2 v2.0.1/go.mod h1:JytRAxdJViV+unUUWedb7uzEy5pgu7OurbqX0eHEikE=
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||||
@@ -125,11 +127,13 @@ github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR3
|
|||||||
github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
|
github.com/hashicorp/go-secure-stdlib/base62 v0.1.1/go.mod h1:EdWO6czbmthiwZ3/PUsDV+UD1D5IRU4ActiaWGwt0Yw=
|
||||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc=
|
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1 h1:cCRo8gK7oq6A2L6LICkUZ+/a5rLiRXFMf1Qd4xSwxTc=
|
||||||
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=
|
github.com/hashicorp/go-secure-stdlib/mlock v0.1.1/go.mod h1:zq93CJChV6L9QTfGKtfBxKqD7BqqXx5O04A/ns2p5+I=
|
||||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 h1:78ki3QBevHwYrVxnyVeaEz+7WtifHhauYF23es/0KlI=
|
|
||||||
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
|
||||||
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6 h1:om4Al8Oy7kCm/B86rLCLah4Dt5Aa0Fr5rYBG60OzwHQ=
|
||||||
|
github.com/hashicorp/go-secure-stdlib/parseutil v0.1.6/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8=
|
||||||
github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo=
|
github.com/hashicorp/go-secure-stdlib/password v0.1.1/go.mod h1:9hH302QllNwu1o2TGYtSk8I8kTAN0ca1EHpwhm5Mmzo=
|
||||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 h1:nd0HIW15E6FG1MsnArYaHfuw9C2zgzM8LxkG5Ty/788=
|
|
||||||
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
|
github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U=
|
||||||
|
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts=
|
||||||
|
github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4=
|
||||||
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs=
|
github.com/hashicorp/go-secure-stdlib/tlsutil v0.1.1/go.mod h1:l8slYwnJA26yBz+ErHpp2IRCLr0vuOMGBORIz4rRiAs=
|
||||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||||
@@ -143,10 +147,10 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
|
|||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hashicorp/vault/api v1.4.1 h1:mWLfPT0RhxBitjKr6swieCEP2v5pp/M//t70S3kMLRo=
|
github.com/hashicorp/vault/api v1.7.2 h1:kawHE7s/4xwrdKbkmwQi0wYaIeUhk5ueek7ljuezCVQ=
|
||||||
github.com/hashicorp/vault/api v1.4.1/go.mod h1:LkMdrZnWNrFaQyYYazWVn7KshilfDidgVBq6YiTq/bM=
|
github.com/hashicorp/vault/api v1.7.2/go.mod h1:xbfA+1AvxFseDzxxdWaL0uO99n1+tndus4GCrtouy0M=
|
||||||
github.com/hashicorp/vault/sdk v0.4.1 h1:3SaHOJY687jY1fnB61PtL0cOkKItphrbLmux7T92HBo=
|
github.com/hashicorp/vault/sdk v0.5.1 h1:zly/TmNgOXCGgWIRA8GojyXzG817POtVh3uzIwzZx+8=
|
||||||
github.com/hashicorp/vault/sdk v0.4.1/go.mod h1:aZ3fNuL5VNydQk8GcLJ2TV8YCRVvyaakYkhZRoVuhj0=
|
github.com/hashicorp/vault/sdk v0.5.1/go.mod h1:DoGraE9kKGNcVgPmTuX357Fm6WAx1Okvde8Vp3dPDoU=
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||||
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
@@ -168,13 +172,16 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
|
|
||||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||||
|
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
|
||||||
|
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
|
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||||
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
|
||||||
@@ -186,14 +193,15 @@ github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdI
|
|||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo=
|
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||||
github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
|
||||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
|
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
@@ -236,8 +244,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||||
|
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||||
@@ -246,8 +255,8 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 h1:0es+/5331RGQPcXlMfP+WrnIIS6dNnNRe0WB02W0F4M=
|
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000 h1:SL+8VVnkqyshUSz5iNnXtrBQzvFF2SkROm6t5RczFAE=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220313003712-b769efc7c000/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
@@ -293,9 +302,10 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a h1:ppl5mZgokTT8uPkmYOyEUmPTr3ypaKkg5eFOGrAmxxE=
|
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
|
||||||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -360,7 +370,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build tools
|
||||||
// +build tools
|
// +build tools
|
||||||
|
|
||||||
package tools
|
package tools
|
||||||
|
|||||||
Reference in new issue
Block a user