feat: add target resource session recording support (#421)
* feat: add target session recording support - add new optional `enable_session_recording` field for enabling or disabling session recording - add new optional `storage_bucket_id` field for setting the storage bucket for the target - These new fields are applicable to Boundary HCP/ENT ### Considerations - There is no test coverage yet until we add support for testing enterprise only features. Manually tested the changes
This commit is contained in:
1 parent
9186304d5d
commit
605d124d51
4 files changed
+143
-1
No files matched your search
@@ -8,6 +8,8 @@ Canonical reference for changes, improvements, and bugfixes for the Boundary Ter
|
|||||||
|
|
||||||
* Add support for a storage bucket as a resource
|
* Add support for a storage bucket as a resource
|
||||||
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/417))
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/417))
|
||||||
|
* Add option to enable session recording on a target resource
|
||||||
|
([PR](https://github.com/hashicorp/terraform-provider-boundary/pull/421))
|
||||||
|
|
||||||
## 1.1.8 (June 13, 2023)
|
## 1.1.8 (June 13, 2023)
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,20 @@ resource "boundary_host_set" "foo" {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "boundary_storage_bucket" "aws_example" {
|
||||||
|
name = "My aws storage bucket"
|
||||||
|
description = "My first storage bucket!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
plugin_name = "aws"
|
||||||
|
bucket_name = "mybucket"
|
||||||
|
attributes_json = jsonencode({ "region" = "us-east-1" })
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"access_key_id" = "aws_access_key_id_value",
|
||||||
|
"secret_access_key" = "aws_secret_access_key_value"
|
||||||
|
})
|
||||||
|
worker_filter = "\"pki\" in \"/tags/type\""
|
||||||
|
}
|
||||||
|
|
||||||
resource "boundary_target" "foo" {
|
resource "boundary_target" "foo" {
|
||||||
name = "foo"
|
name = "foo"
|
||||||
description = "Foo target"
|
description = "Foo target"
|
||||||
@@ -112,6 +126,22 @@ resource "boundary_target" "ssh_foo" {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "boundary_target" "ssh_session_recording_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
|
||||||
|
]
|
||||||
|
enable_session_recording = true
|
||||||
|
storage_bucket_id = boundary_storage_bucket.aws_example
|
||||||
|
}
|
||||||
|
|
||||||
resource "boundary_target" "address_foo" {
|
resource "boundary_target" "address_foo" {
|
||||||
name = "address_foo"
|
name = "address_foo"
|
||||||
description = "Foo target with an address"
|
description = "Foo target with an address"
|
||||||
@@ -138,12 +168,14 @@ resource "boundary_target" "address_foo" {
|
|||||||
- `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.
|
||||||
- `egress_worker_filter` (String) Boolean expression to filter the workers used to access this target
|
- `egress_worker_filter` (String) Boolean expression to filter the workers used to access this target
|
||||||
|
- `enable_session_recording` (Boolean) HCP/Ent Only. Enable sessions recording for this target. Only applicable for SSH targets.
|
||||||
- `host_source_ids` (Set of String) A list of host source ID's. Cannot be used alongside address.
|
- `host_source_ids` (Set of String) A list of host source ID's. Cannot be used alongside address.
|
||||||
- `ingress_worker_filter` (String) HCP Only. Boolean expression to filter the workers a user will connect to when initiating a session against this target
|
- `ingress_worker_filter` (String) HCP Only. Boolean expression to filter the workers a user will connect to when initiating a session against this target
|
||||||
- `injected_application_credential_source_ids` (Set of String) A list of injected application credential 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)
|
||||||
|
- `storage_bucket_id` (String) HCP/Ent Only. Storage bucket for this target. Only applicable for SSH targets.
|
||||||
- `worker_filter` (String, Deprecated) Boolean expression to filter the workers for this target
|
- `worker_filter` (String, Deprecated) Boolean expression to filter the workers for this target
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|||||||
@@ -69,6 +69,20 @@ resource "boundary_host_set" "foo" {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "boundary_storage_bucket" "aws_example" {
|
||||||
|
name = "My aws storage bucket"
|
||||||
|
description = "My first storage bucket!"
|
||||||
|
scope_id = boundary_scope.org.id
|
||||||
|
plugin_name = "aws"
|
||||||
|
bucket_name = "mybucket"
|
||||||
|
attributes_json = jsonencode({ "region" = "us-east-1" })
|
||||||
|
secrets_json = jsonencode({
|
||||||
|
"access_key_id" = "aws_access_key_id_value",
|
||||||
|
"secret_access_key" = "aws_secret_access_key_value"
|
||||||
|
})
|
||||||
|
worker_filter = "\"pki\" in \"/tags/type\""
|
||||||
|
}
|
||||||
|
|
||||||
resource "boundary_target" "foo" {
|
resource "boundary_target" "foo" {
|
||||||
name = "foo"
|
name = "foo"
|
||||||
description = "Foo target"
|
description = "Foo target"
|
||||||
@@ -97,6 +111,22 @@ resource "boundary_target" "ssh_foo" {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resource "boundary_target" "ssh_session_recording_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
|
||||||
|
]
|
||||||
|
enable_session_recording = true
|
||||||
|
storage_bucket_id = boundary_storage_bucket.aws_example
|
||||||
|
}
|
||||||
|
|
||||||
resource "boundary_target" "address_foo" {
|
resource "boundary_target" "address_foo" {
|
||||||
name = "address_foo"
|
name = "address_foo"
|
||||||
description = "Foo target with an address"
|
description = "Foo target with an address"
|
||||||
|
|||||||
@@ -21,8 +21,10 @@ const (
|
|||||||
targetInjectedAppCredentialSourceIdsKey = "injected_application_credential_source_ids"
|
targetInjectedAppCredentialSourceIdsKey = "injected_application_credential_source_ids"
|
||||||
targetDefaultPortKey = "default_port"
|
targetDefaultPortKey = "default_port"
|
||||||
targetDefaultClientPortKey = "default_client_port"
|
targetDefaultClientPortKey = "default_client_port"
|
||||||
|
targetEnableSessionRecordingKey = "enable_session_recording"
|
||||||
targetSessionMaxSecondsKey = "session_max_seconds"
|
targetSessionMaxSecondsKey = "session_max_seconds"
|
||||||
targetSessionConnectionLimitKey = "session_connection_limit"
|
targetSessionConnectionLimitKey = "session_connection_limit"
|
||||||
|
targetStorageBucketIdKey = "storage_bucket_id"
|
||||||
targetWorkerFilterKey = "worker_filter"
|
targetWorkerFilterKey = "worker_filter"
|
||||||
targetWorkerEgressFilterKey = "egress_worker_filter"
|
targetWorkerEgressFilterKey = "egress_worker_filter"
|
||||||
targetWorkerIngressFilterKey = "ingress_worker_filter"
|
targetWorkerIngressFilterKey = "ingress_worker_filter"
|
||||||
@@ -133,6 +135,16 @@ func resourceTarget() *schema.Resource {
|
|||||||
Optional: true,
|
Optional: true,
|
||||||
ConflictsWith: []string{targetHostSourceIdsKey},
|
ConflictsWith: []string{targetHostSourceIdsKey},
|
||||||
},
|
},
|
||||||
|
targetEnableSessionRecordingKey: {
|
||||||
|
Description: "HCP/Ent Only. Enable sessions recording for this target. Only applicable for SSH targets.",
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
targetStorageBucketIdKey: {
|
||||||
|
Description: "HCP/Ent Only. Storage bucket for this target. Only applicable for SSH targets.",
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,7 +190,9 @@ func setFromTargetResponseMap(d *schema.ResourceData, raw map[string]interface{}
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch raw["type"].(string) {
|
typeStr := raw["type"].(string)
|
||||||
|
|
||||||
|
switch typeStr {
|
||||||
case targetTypeTcp, targetTypeSsh:
|
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{})
|
||||||
@@ -194,6 +208,20 @@ func setFromTargetResponseMap(d *schema.ResourceData, raw map[string]interface{}
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SSH only features
|
||||||
|
if typeStr == targetTypeSsh {
|
||||||
|
if sessionRecordingVal, ok := attrs[targetEnableSessionRecordingKey].(bool); ok {
|
||||||
|
if err := d.Set(targetEnableSessionRecordingKey, sessionRecordingVal); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if targetStorageBucketIdVal, ok := attrs[targetStorageBucketIdKey]; ok {
|
||||||
|
if err := d.Set(targetStorageBucketIdKey, targetStorageBucketIdVal); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,6 +292,18 @@ func resourceTargetCreate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enableSessionRecordingVal, ok := d.GetOk(targetEnableSessionRecordingKey)
|
||||||
|
if ok {
|
||||||
|
enableSessionRecordingBool := enableSessionRecordingVal.(bool)
|
||||||
|
opts = append(opts, targets.WithSshTargetEnableSessionRecording(enableSessionRecordingBool))
|
||||||
|
}
|
||||||
|
|
||||||
|
storageBucketIdVal, ok := d.GetOk(targetStorageBucketIdKey)
|
||||||
|
if ok {
|
||||||
|
storageBucketIdStr := storageBucketIdVal.(string)
|
||||||
|
opts = append(opts, targets.WithSshTargetStorageBucketId(storageBucketIdStr))
|
||||||
|
}
|
||||||
|
|
||||||
sessionMaxSecondsVal, ok := d.GetOk(targetSessionMaxSecondsKey)
|
sessionMaxSecondsVal, ok := d.GetOk(targetSessionMaxSecondsKey)
|
||||||
if ok {
|
if ok {
|
||||||
sessionMaxSecondsInt := sessionMaxSecondsVal.(int)
|
sessionMaxSecondsInt := sessionMaxSecondsVal.(int)
|
||||||
@@ -443,6 +483,34 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var enableSessionRecording *bool
|
||||||
|
if d.HasChange(targetEnableSessionRecordingKey) {
|
||||||
|
switch typeStr {
|
||||||
|
case targetTypeSsh:
|
||||||
|
opts = append(opts, targets.WithSshTargetEnableSessionRecording(false))
|
||||||
|
enableSessionRecordingVal, ok := d.GetOk(targetEnableSessionRecordingKey)
|
||||||
|
if ok {
|
||||||
|
enableSessionRecordingBool := enableSessionRecordingVal.(bool)
|
||||||
|
enableSessionRecording = &enableSessionRecordingBool
|
||||||
|
opts = append(opts, targets.WithSshTargetEnableSessionRecording(enableSessionRecordingBool))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var storageBucket *string
|
||||||
|
if d.HasChange(targetStorageBucketIdKey) {
|
||||||
|
switch typeStr {
|
||||||
|
case targetTypeSsh:
|
||||||
|
opts = append(opts, targets.DefaultSshTargetStorageBucketId())
|
||||||
|
storageBucketVal, ok := d.GetOk(targetStorageBucketIdKey)
|
||||||
|
if ok {
|
||||||
|
storageBucketStr := storageBucketVal.(string)
|
||||||
|
storageBucket = &storageBucketStr
|
||||||
|
opts = append(opts, targets.WithSshTargetStorageBucketId(storageBucketStr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var defaultPort *int
|
var defaultPort *int
|
||||||
if d.HasChange(targetDefaultPortKey) {
|
if d.HasChange(targetDefaultPortKey) {
|
||||||
switch typeStr {
|
switch typeStr {
|
||||||
@@ -631,6 +699,16 @@ func resourceTargetUpdate(ctx context.Context, d *schema.ResourceData, meta inte
|
|||||||
return diag.FromErr(err)
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if d.HasChange(targetEnableSessionRecordingKey) {
|
||||||
|
if err := d.Set(targetEnableSessionRecordingKey, enableSessionRecording); err != nil {
|
||||||
|
return diag.FromErr(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if d.HasChange(targetStorageBucketIdKey) {
|
||||||
|
if err := d.Set(targetStorageBucketIdKey, storageBucket); err != nil {
|
||||||
|
return diag.FromErr(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The above call may not actually happen, so we use d.Id() and automatic
|
// The above call may not actually happen, so we use d.Id() and automatic
|
||||||
// versioning here
|
// versioning here
|
||||||
|
|||||||
Reference in new issue
Block a user