From 99a8875d3e4e6800621331973012ded332674e27 Mon Sep 17 00:00:00 2001 From: Timothy Messier Date: Thu, 2 Feb 2023 16:32:19 +0000 Subject: [PATCH 1/3] feat(version): Determine binary version during initalization This ensures that checks for features should work, and bails early if that is not the case, since if this fails the binary is essentially broken. This also simplifies code that performs these checks, ie instead of: binaryVersion, err := version.GetReleaseVersion() if err != nil { // handle error? panic? } if version.SupportsFeature(binaryVersion, version.FeatureA) { // code for FeatureA } else { // without FeatureA } Implementations can do: if version.SupportsFeature(version.Binary, version.FeatureA) { // code for FeatureA } else { // without FeatureA } --- version/feature_manager.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/version/feature_manager.go b/version/feature_manager.go index 32f48a1589..8995c73dcc 100644 --- a/version/feature_manager.go +++ b/version/feature_manager.go @@ -27,16 +27,29 @@ const ( var featureMap map[Feature]MetadataConstraint +// Binary is the version of the running binary. +// This can be used for feature checks. +var Binary *gvers.Version + func init() { + // Do this early to ensure version is valid, if this panics something is + // very broken with the version and any version checks based on the binary's + // version info will not work correctly. Also do this once since the version + // can't change while running. + var err error + Binary, err = GetReleaseVersion() + if err != nil { + panic(err) + } + if featureMap == nil { featureMap = make(map[Feature]MetadataConstraint) } /* Add constraints here following this format after adding a Feature to the Feature iota: - featureConstraint, err := gvers.NewConstraint(">= 0.1.0") // This feature exists at 0.1.0 and above featureMap[FEATURE] = MetadataConstraint{ MetaInfo: []Metadata{OSS, HCP}, - Constraints: featureConstraint, + Constraints: mustNewConstraints(">= 0.1.0"), // This feature exists at 0.1.0 and above } */ } @@ -49,6 +62,14 @@ func metadataStringToMetadata(m string) Metadata { return OSS } +func mustNewConstraints(v string) gvers.Constraints { + c, err := gvers.NewConstraint(v) + if err != nil { + panic(err) + } + return c +} + // Check returns a bool indicating if a version meets the metadata constraint // for a feature. Check returns false if version is nil. func (m MetadataConstraint) Check(version *gvers.Version) bool { From e66ea15fef8e0e84282d0292012e90581839a5a8 Mon Sep 17 00:00:00 2001 From: Timothy Messier Date: Wed, 1 Feb 2023 20:54:08 +0000 Subject: [PATCH 2/3] fix(cli): Status code on api error When using the json output of the cli (`-format=json`), a successful call to the controller API would place the HTTP status code in the JSON as `status_code`. However, if there was an error from the API the status code would be placed in the JSON as `status`. In order to be consistent, this adds a `status_code` field to the error response case. For backwards compatibility it still populates `status` in the error case. This inconsistency was missed partially due to a bug in the CLI tests. The assertion on status code was not valid and would always be successful. Thus this also fixes the assertions and tests. --- CHANGELOG.md | 11 ++++++ internal/cmd/base/format.go | 35 ++++++++++++++----- internal/tests/cli/boundary/_accounts.bash | 2 +- .../cli/boundary/_credential_libraries.bash | 2 +- .../cli/boundary/_credential_stores.bash | 2 +- internal/tests/cli/boundary/_credentials.bash | 6 ++-- internal/tests/cli/boundary/_groups.bash | 10 +++--- internal/tests/cli/boundary/_helpers.bash | 5 ++- .../tests/cli/boundary/_host_catalogs.bash | 6 ++-- internal/tests/cli/boundary/_hosts.bash | 10 +++--- internal/tests/cli/boundary/_roles.bash | 28 +++++++-------- internal/tests/cli/boundary/_scopes.bash | 8 ++--- internal/tests/cli/boundary/_targets.bash | 14 ++++---- internal/tests/cli/boundary/_users.bash | 6 ++-- internal/tests/cli/boundary/_workers.bash | 6 ++-- .../cli/boundary/credential_libraries.bats | 7 ++++ version/feature_manager.go | 5 +++ 17 files changed, 101 insertions(+), 62 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcbbbda238..e612959424 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,12 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. subcommand, will have the subtype set to `vault-generic`. The deprecated subtype and subcommands will be removed in boundary 0.14.0, at which point `vault-generic` must be used. +* In Boundary 0.1.8 using the `-format=json` option with the cli would provide + a `status_code` for successful API requests from the cli. However, in the + case where an error was returned, the JSON would use `status` instead. This + inconsistency has been fixed, with `status_code` being used in both cases. + For error cases `status` will still be populated, but is deprecated and will + be removed in 0.14.0. ### New and Improved @@ -68,6 +74,11 @@ Canonical reference for changes, improvements, and bugfixes for Boundary. * data warehouse: Fix bug that caused credential dimensions to not get associated with session facts ([PR](https://github.com/hashicorp/boundary/pull/2787)). * sessions: Fix two authorizeSession race conditions in handleProxy. ([PR](https://github.com/hashicorp/boundary/pull/2795)) +* cli: When using `-format=json` the JSON was inconsistent in how it reported + status codes. In successful cases it would use `status_code`, but in error + cases it would use `status`. Now `status_code` is used in both cases. In + error cases `status` is still populated, see the deprecations above for + more details. ([PR](https://github.com/hashicorp/boundary/pull/2887)) ## 0.11.2 (2022/12/09) diff --git a/internal/cmd/base/format.go b/internal/cmd/base/format.go index a72b3ec038..5db3e1797e 100644 --- a/internal/cmd/base/format.go +++ b/internal/cmd/base/format.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/boundary/api" "github.com/hashicorp/boundary/api/plugins" "github.com/hashicorp/boundary/api/scopes" + "github.com/hashicorp/boundary/version" "github.com/mitchellh/cli" "github.com/mitchellh/go-wordwrap" "github.com/pkg/errors" @@ -181,16 +182,32 @@ func (c *Command) PrintApiError(in *api.Error, contextStr string, opt ...Option) opts := getOpts(opt...) switch Format(c.UI) { case "json": - output := struct { - Context string `json:"context,omitempty"` - Status int `json:"status"` - ApiError json.RawMessage `json:"api_error"` - }{ - Context: contextStr, - Status: in.Response().StatusCode(), - ApiError: in.Response().Body.Bytes(), + var b []byte + if version.SupportsFeature(version.Binary, version.IncludeStatusInCli) { + output := struct { + Context string `json:"context,omitempty"` + StatusCode int `json:"status_code"` + Status int `json:"status"` + ApiError json.RawMessage `json:"api_error"` + }{ + Context: contextStr, + StatusCode: in.Response().StatusCode(), + Status: in.Response().StatusCode(), + ApiError: in.Response().Body.Bytes(), + } + b, _ = JsonFormatter{}.Format(output) + } else { + output := struct { + Context string `json:"context,omitempty"` + StatusCode int `json:"status_code"` + ApiError json.RawMessage `json:"api_error"` + }{ + Context: contextStr, + StatusCode: in.Response().StatusCode(), + ApiError: in.Response().Body.Bytes(), + } + b, _ = JsonFormatter{}.Format(output) } - b, _ := JsonFormatter{}.Format(output) c.UI.Error(string(b)) default: diff --git a/internal/tests/cli/boundary/_accounts.bash b/internal/tests/cli/boundary/_accounts.bash index 9444bc31ad..a7fd24abf5 100644 --- a/internal/tests/cli/boundary/_accounts.bash +++ b/internal/tests/cli/boundary/_accounts.bash @@ -8,7 +8,7 @@ function read_account() { } function delete_account() { - boundary accounts delete -id $1 + boundary accounts delete -id $1 -format json } function list_accounts() { diff --git a/internal/tests/cli/boundary/_credential_libraries.bash b/internal/tests/cli/boundary/_credential_libraries.bash index 606399e6b6..6d3c43646e 100644 --- a/internal/tests/cli/boundary/_credential_libraries.bash +++ b/internal/tests/cli/boundary/_credential_libraries.bash @@ -20,7 +20,7 @@ function read_credential_library() { } function delete_credential_library() { - boundary credential-libraries delete -id $1 + boundary credential-libraries delete -id $1 -format json } function list_credential_libraries() { diff --git a/internal/tests/cli/boundary/_credential_stores.bash b/internal/tests/cli/boundary/_credential_stores.bash index 26a8fb9077..8255564221 100644 --- a/internal/tests/cli/boundary/_credential_stores.bash +++ b/internal/tests/cli/boundary/_credential_stores.bash @@ -19,7 +19,7 @@ function read_credential_store() { } function delete_credential_store() { - boundary credential-stores delete -id $1 + boundary credential-stores delete -id $1 -format json } function list_credential_stores() { diff --git a/internal/tests/cli/boundary/_credentials.bash b/internal/tests/cli/boundary/_credentials.bash index 4a37b0aada..0d17bfd19a 100644 --- a/internal/tests/cli/boundary/_credentials.bash +++ b/internal/tests/cli/boundary/_credentials.bash @@ -5,7 +5,7 @@ function create_username_password_credential() { local sid=$2 local user=$3 local pass=$4 - + export BP="${pass}" boundary credentials create username-password \ -name $name \ @@ -32,7 +32,7 @@ function read_credential() { } function delete_credential() { - boundary credentials delete -id $1 + boundary credentials delete -id $1 -format json } function list_credentials() { @@ -42,6 +42,6 @@ function list_credentials() { function credential_id() { local name=$1 local sid=$2 - + strip $(list_credentials $sid | jq -c ".items[] | select(.name | contains(\"$name\")) | .[\"id\"]") } diff --git a/internal/tests/cli/boundary/_groups.bash b/internal/tests/cli/boundary/_groups.bash index ec7b721792..61202e0feb 100644 --- a/internal/tests/cli/boundary/_groups.bash +++ b/internal/tests/cli/boundary/_groups.bash @@ -9,7 +9,7 @@ function read_group() { } function delete_group() { - boundary groups delete -id $1 + boundary groups delete -id $1 -format json } function list_groups() { @@ -27,7 +27,7 @@ function group_id() { function group_member_ids() { local gid=$1 - boundary groups read -id $gid -format json | jq '.item["members"][]["id"]' + boundary groups read -id $gid -format json | jq '.item["members"][]["id"]' } function group_has_member_id() { @@ -36,10 +36,10 @@ function group_has_member_id() { ids=$(group_member_ids $gid) for id in $ids; do if [ $(strip "$id") == "$mid" ]; then - return 0 + return 0 fi done - return 1 + return 1 } function has_default_group_actions() { @@ -51,6 +51,6 @@ function has_default_group_actions() { $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" return 1 - } + } done } diff --git a/internal/tests/cli/boundary/_helpers.bash b/internal/tests/cli/boundary/_helpers.bash index 9a9c331250..efa9d49d3d 100644 --- a/internal/tests/cli/boundary/_helpers.bash +++ b/internal/tests/cli/boundary/_helpers.bash @@ -24,9 +24,8 @@ function strip_all() { function has_status_code() { local json=$1 local code=$2 - if [ echo "$json"|jq -c ".status_code == $code" ]; then - return 1 - fi + echo "checking .status_code == $code in $json" + echo "$json" | jq -e ".status_code == $code" } diag() { diff --git a/internal/tests/cli/boundary/_host_catalogs.bash b/internal/tests/cli/boundary/_host_catalogs.bash index fdfe55a4cf..6b61f3383a 100644 --- a/internal/tests/cli/boundary/_host_catalogs.bash +++ b/internal/tests/cli/boundary/_host_catalogs.bash @@ -15,7 +15,7 @@ function read_host_catalog() { } function delete_host_catalog() { - boundary host-catalogs delete -id $1 + boundary host-catalogs delete -id $1 -format json } function list_host_catalogs() { @@ -35,7 +35,7 @@ function has_default_host_catalog_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/_hosts.bash b/internal/tests/cli/boundary/_hosts.bash index 7be00c4ef9..3a14b619c3 100644 --- a/internal/tests/cli/boundary/_hosts.bash +++ b/internal/tests/cli/boundary/_hosts.bash @@ -3,7 +3,7 @@ load _authorized_actions function create_host() { local name=$1 local hcid=$2 - + boundary hosts create static \ -name $name \ -description 'test host' \ @@ -16,7 +16,7 @@ function read_host() { } function delete_host() { - boundary hosts delete -id $1 + boundary hosts delete -id $1 -format json } function list_hosts() { @@ -26,7 +26,7 @@ function list_hosts() { function host_id() { local name=$1 local hcid=$2 - + strip $(list_hosts $hcid | jq -c ".items[] | select(.name | contains(\"$name\")) | .[\"id\"]") } @@ -37,7 +37,7 @@ function has_default_host_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/_roles.bash b/internal/tests/cli/boundary/_roles.bash index 55b026f112..f689f9c7ae 100644 --- a/internal/tests/cli/boundary/_roles.bash +++ b/internal/tests/cli/boundary/_roles.bash @@ -4,7 +4,7 @@ function create_role() { local sid=$1 local name=$2 local gsid=$3 - + boundary roles create \ -scope-id $sid \ -name $name \ @@ -17,7 +17,7 @@ function read_role() { } function delete_role() { - boundary roles delete -id $1 + boundary roles delete -id $1 -format json } function list_roles() { @@ -27,28 +27,28 @@ function list_roles() { function assoc_role_grant() { local grant=$1 local id=$2 - + boundary roles add-grants -grant $grant -id $id } function assoc_role_principal() { local principal=$1 local id=$2 - - boundary roles add-principals -principal $principal -id $id + + boundary roles add-principals -principal $principal -id $id } function remove_role_grant() { local grant=$1 local id=$2 - + boundary roles remove-grants -grant $grant -id $id } function remove_role_principal() { local principal=$1 local id=$2 - + boundary roles remove-principals -principal $principal -id $id } @@ -60,7 +60,7 @@ function role_id() { function role_principal_ids() { local rid=$1 - strip $(read_role $rid | jq '.item["principals"][]["id"]') + strip $(read_role $rid | jq '.item["principals"][]["id"]') } function role_has_principal_id() { @@ -69,10 +69,10 @@ function role_has_principal_id() { local ids=$(role_principal_ids $rid) for id in $ids; do if [ $(strip "$id") == "$pid" ]; then - return 0 + return 0 fi done - return 1 + return 1 } function role_grants() { @@ -86,10 +86,10 @@ function role_has_grant() { local hasgrants=$(role_grants $rid) for grant in $hasgrants; do if [ $(strip_all "$grant") == "$g" ]; then - return 0 + return 0 fi done - return 1 + return 1 } function has_default_role_actions() { @@ -99,7 +99,7 @@ function has_default_role_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/_scopes.bash b/internal/tests/cli/boundary/_scopes.bash index 84032c3524..8624adca05 100644 --- a/internal/tests/cli/boundary/_scopes.bash +++ b/internal/tests/cli/boundary/_scopes.bash @@ -16,7 +16,7 @@ function read_scope() { function delete_scope() { local sid=$1 - boundary scopes delete -id $sid + boundary scopes delete -id $sid -format json } function list_scopes() { @@ -26,7 +26,7 @@ function list_scopes() { function scope_id() { local name=$1 local sid=$2 - + strip $(list_scopes $sid | jq -c ".items[] | select(.name | contains(\"$name\")) | .[\"id\"]") } @@ -37,7 +37,7 @@ function has_default_scope_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/_targets.bash b/internal/tests/cli/boundary/_targets.bash index 5e7644d152..ae786bf727 100644 --- a/internal/tests/cli/boundary/_targets.bash +++ b/internal/tests/cli/boundary/_targets.bash @@ -32,7 +32,7 @@ function read_target() { } function delete_target() { - boundary targets delete -id $1 + boundary targets delete -id $1 -format json } function list_targets() { @@ -65,20 +65,20 @@ function target_id_from_name() { function target_host_source_ids() { local tid=$1 - boundary targets read -id $tid -format json | jq '.item.host_sources[].id' + boundary targets read -id $tid -format json | jq '.item.host_sources[].id' } function target_has_host_source_id() { local tid=$1 local hsid=$2 - ids=$(target_host_source_ids $tid) + ids=$(target_host_source_ids $tid) for id in $ids; do if [ $(strip "$id") == "$hsid" ]; then - return 0 + return 0 fi done - return 1 + return 1 } function has_default_target_actions() { @@ -88,7 +88,7 @@ function has_default_target_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/_users.bash b/internal/tests/cli/boundary/_users.bash index 315bef4b9b..92b4b5e284 100644 --- a/internal/tests/cli/boundary/_users.bash +++ b/internal/tests/cli/boundary/_users.bash @@ -9,7 +9,7 @@ function read_user() { } function delete_user() { - boundary users delete -id $1 + boundary users delete -id $1 -format json } function list_users() { @@ -28,8 +28,8 @@ function has_default_user_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/_workers.bash b/internal/tests/cli/boundary/_workers.bash index a429e589f1..adb0c8c615 100644 --- a/internal/tests/cli/boundary/_workers.bash +++ b/internal/tests/cli/boundary/_workers.bash @@ -15,7 +15,7 @@ function update_worker() { } function delete_worker() { - boundary workers delete -id $1 + boundary workers delete -id $1 -format json } function list_workers() { @@ -34,7 +34,7 @@ function has_default_worker_actions() { for action in ${actions[@]}; do $(has_authorized_action "$out" "$action") || { echo "failed to find $action action in output: $out" - return 1 - } + return 1 + } done } diff --git a/internal/tests/cli/boundary/credential_libraries.bats b/internal/tests/cli/boundary/credential_libraries.bats index 10077ff4a3..c26405bf9d 100755 --- a/internal/tests/cli/boundary/credential_libraries.bats +++ b/internal/tests/cli/boundary/credential_libraries.bats @@ -73,6 +73,13 @@ export NEW_VAULT_LIB="test_vault" [ "$status" -eq 0 ] run has_status_code "$output" "204" [ "$status" -eq 0 ] + + run delete_credential_library $clid + echo "$output" + [ "$status" -eq 1 ] + run has_status_code "$output" "404" + echo "$output" + [ "$status" -eq 0 ] } @test "boundary/credential-libraries: can create $NEW_VAULT_LIB vault library in credential store $NEW_STORE deprecated subcommand" { diff --git a/version/feature_manager.go b/version/feature_manager.go index 8995c73dcc..0628d9e766 100644 --- a/version/feature_manager.go +++ b/version/feature_manager.go @@ -23,6 +23,7 @@ type Feature int const ( UnknownFeature Feature = iota MultiHopSessionFeature + IncludeStatusInCli ) var featureMap map[Feature]MetadataConstraint @@ -52,6 +53,10 @@ func init() { Constraints: mustNewConstraints(">= 0.1.0"), // This feature exists at 0.1.0 and above } */ + featureMap[IncludeStatusInCli] = MetadataConstraint{ + MetaInfo: []Metadata{OSS, HCP}, + Constraints: mustNewConstraints("< 0.14.0"), + } } func metadataStringToMetadata(m string) Metadata { From f9a2f44f5bf2a73c2d8b33d0a9351cac3c64e182 Mon Sep 17 00:00:00 2001 From: Timothy Messier Date: Wed, 1 Feb 2023 20:54:41 +0000 Subject: [PATCH 3/3] test(cli): Add tests for vault-ssh-certificate credential library This adds tests for updating specific fields of the credential library. --- .../cli/boundary/_credential_libraries.bash | 5 + internal/tests/cli/boundary/_helpers.bash | 8 + .../cli/boundary/credential_libraries.bats | 411 ++++++++++++++++++ 3 files changed, 424 insertions(+) mode change 100755 => 100644 internal/tests/cli/boundary/credential_libraries.bats diff --git a/internal/tests/cli/boundary/_credential_libraries.bash b/internal/tests/cli/boundary/_credential_libraries.bash index 6d3c43646e..b5bf1270e0 100644 --- a/internal/tests/cli/boundary/_credential_libraries.bash +++ b/internal/tests/cli/boundary/_credential_libraries.bash @@ -5,6 +5,11 @@ function create_vault_ssh_certificate_library() { create vault-ssh-certificate $@ } +function update_vault_ssh_certificate_library() { + boundary credential-libraries \ + update vault-ssh-certificate $@ +} + function create_vault_generic_library() { boundary credential-libraries \ create vault-generic $@ diff --git a/internal/tests/cli/boundary/_helpers.bash b/internal/tests/cli/boundary/_helpers.bash index efa9d49d3d..68ff2d2a30 100644 --- a/internal/tests/cli/boundary/_helpers.bash +++ b/internal/tests/cli/boundary/_helpers.bash @@ -31,3 +31,11 @@ function has_status_code() { diag() { echo "$@" | sed -e 's/^/# /' >&3 ; } + +function field_eq() { + local json=$1 + local field=$2 + local expected=$3 + echo "checking $field == $expected in $json" + echo "$json" | jq -e "$field == $expected" +} diff --git a/internal/tests/cli/boundary/credential_libraries.bats b/internal/tests/cli/boundary/credential_libraries.bats old mode 100755 new mode 100644 index c26405bf9d..f7e7ae30d5 --- a/internal/tests/cli/boundary/credential_libraries.bats +++ b/internal/tests/cli/boundary/credential_libraries.bats @@ -162,6 +162,417 @@ export NEW_VAULT_LIB="test_vault" [ "$status" -eq 0 ] } +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library ecdsa-256" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type ecdsa -key-bits 256 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ecdsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "256" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library ecdsa-384" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type ecdsa -key-bits 384 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ecdsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "384" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library ecdsa-521" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type ecdsa -key-bits 521 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ecdsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "521" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library ecdsa-0" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type ecdsa -key-bits 0 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ecdsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "256" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library rsa-2048" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type rsa -key-bits 2048 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"rsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "2048" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library rsa-3072" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type rsa -key-bits 3072 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"rsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "3072" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library rsa-4096" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type rsa -key-bits 4096 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"rsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "4096" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library rsa-0" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type rsa -key-bits 0 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"rsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "2048" + [ "$status" -eq 0 ] +} + + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library ed25519" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + run update_vault_ssh_certificate_library -id $clid -key-type ed25519 -key-bits null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ed25519"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "null" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library key_type default" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + + # set to something other than the default + run update_vault_ssh_certificate_library -id $clid -key-type ecdsa -key-bits 384 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ecdsa"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "384" + [ "$status" -eq 0 ] + + # now set to the default + run update_vault_ssh_certificate_library -id $clid -key-type null -key-bits null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_type" '"ed25519"' + [ "$status" -eq 0 ] + run field_eq "$got" ".item.attributes.key_bits" "null" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library ttl" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + + # can set it + run update_vault_ssh_certificate_library -id $clid -ttl 1d + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.ttl" '"1d"' + [ "$status" -eq 0 ] + + # can unset it + run update_vault_ssh_certificate_library -id $clid -ttl null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.ttl" "null" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library key_id" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + + # can set it + run update_vault_ssh_certificate_library -id $clid -key-id id + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_id" '"id"' + [ "$status" -eq 0 ] + + # can unset it + run update_vault_ssh_certificate_library -id $clid -key-id null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_id" "null" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library extensions" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + + # can set it + run update_vault_ssh_certificate_library -id $clid -extension permit-pty + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.extensions" '{"permit-pty":""}' + [ "$status" -eq 0 ] + + # can set multiple + run update_vault_ssh_certificate_library -id $clid -extension permit-pty -extension permit-X11-forwarding + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.extensions" '{"permit-X11-forwarding":"","permit-pty":""}' + [ "$status" -eq 0 ] + + # can unset it + run update_vault_ssh_certificate_library -id $clid -extensions null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.extensions" "null" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library critical-options" { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + + # can set it + run update_vault_ssh_certificate_library -id $clid -critical-option force-command=/bin/foo + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" '.item.attributes.critical_options["force-command"]' '"/bin/foo"' + [ "$status" -eq 0 ] + + # can set multiple + run update_vault_ssh_certificate_library -id $clid -critical-option force-command=/bin/foo -critical-option source-address=10.0.0.1/32 + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" '.item.attributes.critical_options["force-command"]' '"/bin/foo"' + [ "$status" -eq 0 ] + run field_eq "$got" '.item.attributes.critical_options["source-address"]' '"10.0.0.1/32"' + [ "$status" -eq 0 ] + + # can unset it + run update_vault_ssh_certificate_library -id $clid -extensions null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.extensions" "null" + [ "$status" -eq 0 ] +} + +@test "boundary/credential-libraries: can update $NEW_VAULT_LIB vault-ssh-certificate library " { + skip_if_no_vault + + local csid=$(credential_store_id $NEW_STORE $DEFAULT_P_ID) + local clid=$(credential_library_id $NEW_VAULT_LIB $csid) + + # can set a ttl + run update_vault_ssh_certificate_library -id $clid -key-id id + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_id" '"id"' + [ "$status" -eq 0 ] + + # can unset it + run update_vault_ssh_certificate_library -id $clid -key-id null + echo "$output" + [ "$status" -eq 0 ] + + run read_credential_library $clid + echo "$output" + [ "$status" -eq 0 ] + got=$(echo "$output") + + run field_eq "$got" ".item.attributes.key_id" "null" + [ "$status" -eq 0 ] +} + @test "boundary/credential-libraries: can delete $NEW_VAULT_LIB vault-ssh-certificate library" { skip_if_no_vault